天涯海角异孤星
rand.Intn()
函数是个伪随机函数,不管运行多少次都只会返回同样的随机数,因为它默认的资源就是单一值,所以必须调用 rand.Seed()
, 并且传入一个变化的值作为参数,如 time.Now().UnixNano()
, 就是可以生成时刻变化的值。rand.Intn(n)
返回值为 [0,n)
之间的整数。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 初始化随机数的资源库, 如果不执行这行, 不管运行多少次都返回同样的值
rand.Seed(time.Now().UnixNano())
// rand.Intn(100) 返回随机值为 0-99
fmt.Println("A number from 1-100:", 1+rand.Intn(100))
}
你可以使用 go-assets 将静态资源打包到可执行文件中。
其实,是使用 go-assets-builder 命令将目录下的资源文件打包到一个 assets.go 文件里,然后就可以只引用 assets.go 实现文件访问,不再依赖于原先的静态资源目录。
直接看官网的例子吧:https://github.com/gin-gonic/examples/tree/master/assets-in-binary
示例代码:
func main() {
router := gin.Default()
router.Static("/assets", "./assets")
router.StaticFS("/more_static", http.Dir("my_file_system"))
router.StaticFile("/favicon.ico", "./resources/favicon.ico")
// 监听并在 0.0.0.0:8080 上启动服务
router.Run(":8080")
}
其中
router.Static
指定某个目录为静态资源目录,可直接访问这个目录下的资源,url 要具体到资源名称。router.StaticFS
比前面一个多了个功能,当目录下不存 index.html 文件时,会列出该目录下的所有文件。router.StaticFile
指定某个具体的文件作为静态资源访问。HTTP 重定向很容易。 内部、外部重定向均支持。
外部重定向使用 Redirct
,路由重定向使用 HandleContext
:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/test", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://www.yangdx.com/")
})
r.GET("/test1", func(c *gin.Context) {
c.Request.URL.Path = "/test2"
r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"hello": "world"})
})
r.Run(":8080")
}
请参阅 issues 并尝试以下示例:
package main
import (
"log"
"net/http"
"time"
"github.com/gin-gonic/gin"
"golang.org/x/sync/errgroup"
)
var (
g errgroup.Group
)
func router01() http.Handler {
e := gin.New()
e.Use(gin.Recovery())
e.GET("/", func(c *gin.Context) {
c.JSON(
http.StatusOK,
gin.H{
"code": http.StatusOK,
"error": "Welcome server 01",
},
)
})
return e
}
func router02() http.Handler {
e := gin.New()
e.Use(gin.Recovery())
e.GET("/", func(c *gin.Context) {
c.JSON(
http.StatusOK,
gin.H{
"code": http.StatusOK,
"error": "Welcome server 02",
},
)
})
return e
}
func main() {
server01 := &http.Server{
Addr: ":8080",
Handler: router01(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
server02 := &http.Server{
Addr: ":8081",
Handler: router02(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
g.Go(func() error {
return server01.ListenAndServe()
})
g.Go(func() error {
return server02.ListenAndServe()
})
if err := g.Wait(); err != nil {
log.Fatal(err)
}
}
两种解决方式:
git clone https://github.com/golang/sys.git $GOPATH/src/github.com/golang/sys
git clone https://github.com/golang/net.git $GOPATH/src/github.com/golang/net
git clone https://github.com/golang/text.git $GOPATH/src/github.com/golang/text
git clone https://github.com/golang/lint.git $GOPATH/src/github.com/golang/lint
git clone https://github.com/golang/tools.git $GOPATH/src/github.com/golang/tools
git clone https://github.com/golang/crypto.git $GOPATH/src/github.com/golang/crypto
ln -s $GOPATH/src/github.com/golang/ $GOPATH/src/golang.org/x
go env 查看 go path
进入或创建目录:
$GOPATH/src/golang.org/x
进入目录,git clone github.com上项目代替
git clone https://github.com/golang/sys.git
git clone https://github.com/golang/net.git
git clone https://github.com/golang/text.git
git clone https://github.com/golang/lint.git
git clone https://github.com/golang/tools.git
git clone https://github.com/golang/crypto.git
代码:
func main() {
router := gin.Default()
// 简单的路由组: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
// 简单的路由组: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
router.Run(":8080")
}
示例代码:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
// 此 handler 将匹配 /user/john 但不会匹配 /user/ 或者 /user
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
// 此 handler 将匹配 /user/john/ 和 /user/john/send
// 如果没有其他路由匹配 /user/john,它将重定向到 /user/john/
router.GET("/user/:name/*action", func(c *gin.Context) {
name := c.Param("name")
action := c.Param("action")
message := name + " is " + action
c.String(http.StatusOK, message)
})
router.Run(":8080")
}
示例代码:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
cookie, err := c.Cookie("gin_cookie")
if err != nil {
cookie = "NotSet"
c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", http.SameSiteDefaultMode, false, true)
}
fmt.Printf("Cookie value: %s \n", cookie)
})
router.Run()
}
c.SetCookie
的第6个参数是设置 Cookie 的 SameSite 属性,可以用以下常量表示:http.SameSiteDefaultMode
、http.SameSiteLaxMode
、http.SameSiteStrictMode
、http.SameSiteNoneMode
关于 SamSite 的资料请阅读:http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html