├── .gitignore ├── README.md ├── files ├── .gitignore ├── admin.css ├── header.jpg └── style.css ├── go.mod ├── go.sum ├── site.go └── templates ├── admin.html └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.db 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang example site 2 | Example represent small site with admin-panel. 3 | 4 | ## Requirements 5 | 6 | Go 1.11 or above. 7 | 8 | ## Installation 9 | 10 | Run the following command to get the sources: 11 | 12 | ``` 13 | git clone https://github.com/night-codes/golang-site-example 14 | cd golang-site-example 15 | go get -u 16 | ``` 17 | 18 | Start the application: 19 | 20 | ``` 21 | go run . 22 | ``` 23 | 24 | Now the application runned on address [http://localhost:8080/](http://localhost:8080/). 25 | 26 | ## Admin Panel 27 | You can found the admin panel by address [http://localhost:8080/admin/](http://localhost:8080/admin/). 28 | Username/Password: `admin secret` 29 | -------------------------------------------------------------------------------- /files/.gitignore: -------------------------------------------------------------------------------- 1 | *.fasthttp.gz 2 | -------------------------------------------------------------------------------- /files/admin.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | header { 6 | background: #446688; 7 | padding: 10px; 8 | color: rgba(255, 255, 255, 0.7); 9 | font-size: 3rem; 10 | } 11 | .container { 12 | max-width: 1024px; 13 | margin: 0 auto; 14 | } 15 | form>div { 16 | margin-top: 1rem; 17 | font-size: 1rem; 18 | } 19 | input, textarea { 20 | padding: 0.5rem; 21 | } 22 | .err { 23 | background: #fee; 24 | color: #873A3A; 25 | padding: 1.5rem; 26 | } 27 | .ok { 28 | background: #efe; 29 | color: #115F17; 30 | padding: 1.5rem; 31 | } 32 | table { 33 | border-radius: 3px; 34 | width: 100%; 35 | border: #e3e3e3 1px solid; 36 | padding: 0px; 37 | background: #ffffff; 38 | padding-top: 0px; 39 | border-collapse: collapse; 40 | font-size: 96%; 41 | } 42 | table tr>th { 43 | padding: 0.5rem 0.7rem; 44 | background-color: #3D464D; 45 | border: #3D464D 1px dotted; 46 | border-right: #999999 1px dotted; 47 | color: #ffffff; 48 | border-top: 1px #777777 solid !important; 49 | border-right: 1px #777777 solid !important 50 | } 51 | table tr>td { 52 | padding: 0.5rem 0.7rem; 53 | border: #e3e3e3 1px solid; 54 | } 55 | table tr:nth-child(odd)>td { 56 | background-color: #f8f8f8; 57 | } 58 | -------------------------------------------------------------------------------- /files/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/night-codes/golang-site-example/3801f6614b22ccbb8966e3ea1a66ad156e2e8209/files/header.jpg -------------------------------------------------------------------------------- /files/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | header { 6 | background: url("header.jpg") bottom; 7 | padding: 50px; 8 | color: rgba(255, 255, 255, 0.7); 9 | font-size: 3rem; 10 | } 11 | .container { 12 | max-width: 1024px; 13 | margin: 0 auto; 14 | } 15 | form>div { 16 | margin-top: 1rem; 17 | font-size: 1rem; 18 | } 19 | input, textarea { 20 | padding: 0.5rem; 21 | } 22 | .err { 23 | background: #fee; 24 | color: #873A3A; 25 | padding: 1.5rem; 26 | } 27 | .ok { 28 | background: #efe; 29 | color: #115F17; 30 | padding: 1.5rem; 31 | } 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module golang-site-example 2 | 3 | go 1.11 4 | 5 | require ( 6 | github.com/night-codes/tokay v1.4.2 7 | gorm.io/driver/sqlite v1.1.5 8 | gorm.io/gorm v1.21.15 9 | ) 10 | 11 | require ( 12 | github.com/andybalholm/brotli v1.0.3 // indirect 13 | github.com/jinzhu/inflection v1.0.0 // indirect 14 | github.com/jinzhu/now v1.1.2 // indirect 15 | github.com/klauspost/compress v1.13.6 // indirect 16 | github.com/mattn/go-sqlite3 v1.14.8 // indirect 17 | github.com/night-codes/govalidator v1.0.4 // indirect 18 | github.com/night-codes/tokay-render v1.0.2 // indirect 19 | github.com/night-codes/tokay-websocket v1.0.0 // indirect 20 | github.com/valyala/bytebufferpool v1.0.0 // indirect 21 | github.com/valyala/fasthttp v1.30.0 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 2 | github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= 3 | github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 4 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 7 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 8 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 9 | github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= 10 | github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 11 | github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 12 | github.com/klauspost/compress v1.13.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 13 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 14 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= 15 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 16 | github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 17 | github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= 18 | github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 19 | github.com/night-codes/govalidator v1.0.4 h1:MPPrWKLDw0P1Dunqgoh4VCiOq8jjpW1RqjQ3XYQE52Q= 20 | github.com/night-codes/govalidator v1.0.4/go.mod h1:698OUuzQEHaly/WE4iDX2Zq9XUD9tlIubaKTtqDgJvE= 21 | github.com/night-codes/tokay v1.4.2 h1:2FbSk13/rBXHXlu7IVKzQvX3pCluY3gPvLU+EiA38ME= 22 | github.com/night-codes/tokay v1.4.2/go.mod h1:2ohDuQ/JkoAqAyVKXhnOE8VptxAtuSaKf3/Guv7rUYY= 23 | github.com/night-codes/tokay-render v1.0.2 h1:llMZ9rqk7qcJdYxKKiXLTwgckmJjp6/jTDjYi/JHSx0= 24 | github.com/night-codes/tokay-render v1.0.2/go.mod h1:luRmj6jFl2hpI21p039tjz/E+z8v1zfZ6tH3Kmihj58= 25 | github.com/night-codes/tokay-websocket v1.0.0 h1:2/Dx6vSyMCxw6IkhhaODKQDgzJaF0BeQpp8mBNTVAGM= 26 | github.com/night-codes/tokay-websocket v1.0.0/go.mod h1:ihLq/OaMOFoaKayuSeXuJ+6i0h56JXmoRvqJiOQklGc= 27 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 28 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 29 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 30 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 31 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 32 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 33 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 34 | github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= 35 | github.com/valyala/fasthttp v1.30.0 h1:nBNzWrgZUUHohyLPU/jTvXdhrcaf2m5k3bWk+3Q049g= 36 | github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 37 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 38 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 39 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 40 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 41 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 43 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 44 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 45 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 46 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 47 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 48 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 49 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 50 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 51 | gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs= 52 | gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc= 53 | gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk= 54 | gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 55 | -------------------------------------------------------------------------------- /site.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/night-codes/tokay" 5 | "gorm.io/driver/sqlite" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type ( 10 | obj map[string]interface{} 11 | feedback struct { 12 | ID uint64 `form:"id" gorm:"primary_key"` 13 | Name string `form:"name" valid:"required,min(3),max(40)"` 14 | Title string `form:"title" valid:"required,max(150)"` 15 | Message string `form:"message" valid:"required"` 16 | } 17 | ) 18 | 19 | func main() { 20 | db, err := gorm.Open(sqlite.Open("site.db"), &gorm.Config{}) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | db.AutoMigrate(&feedback{}) 26 | 27 | r := tokay.New() 28 | r.Static("/files", "./files") 29 | 30 | r.GET("/", func(c *tokay.Context) { 31 | c.HTML(200, "index", obj{"title": "My website", "name": `My Friend`}) 32 | }) 33 | 34 | r.POST("/", func(c *tokay.Context) { 35 | fb := feedback{} 36 | ret := obj{"title": "My website", "name": `My Friend`} 37 | if err := c.Bind(&fb); err != nil { 38 | ret["err"] = "Oops, an error: " + err.Error() 39 | } else { 40 | if err := db.Save(&fb).Error; err != nil { 41 | ret["err"] = "Unexpected error. Come back to us later." 42 | } else { 43 | ret["ok"] = "Thanks for your feedback!" 44 | } 45 | } 46 | 47 | c.HTML(200, "index", ret) 48 | }) 49 | 50 | admin := r.Group("/admin", tokay.BasicAuth("admin", "secret")) 51 | admin.GET("/", func(c *tokay.Context) { 52 | feedbacks := []feedback{} 53 | db.Find(&feedbacks) 54 | c.HTML(200, "admin", obj{"feedbacks": feedbacks}) 55 | }) 56 | 57 | panic(r.Run(":8080")) 58 | } 59 | -------------------------------------------------------------------------------- /templates/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Админка 5 | 6 | 7 | 8 | 9 |
10 |
Admin panel
11 |
12 |
13 |

Feedbacks:

14 | 15 | 16 | 17 | 18 | 19 | 20 | {{if .feedbacks}} {{range .feedbacks}} 21 | 22 | 23 | 24 | 25 | 26 | {{end}} {{else}} 27 | 28 | 29 | 30 | {{end}} 31 |
NameTopicMessage
{{.Name}}{{.Title}}{{.Message}}
Нет записей
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{.title}} 5 | 6 | 7 | 8 | 9 |
10 |
{{.title}}
11 |
12 |
13 |

Hello {{.name}}!

14 |
15 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

16 |
17 |
18 |

Give feedback

19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | {{if .ok}} 34 |
35 | {{.ok}} 36 |
37 | {{end}} {{if .err}} 38 |
39 | {{.err}} 40 |
41 | {{end}} 42 |
43 | 44 | 45 | --------------------------------------------------------------------------------