Buffer-String()-和-Buffer-String()
b1 := bytes.Buffer{} // 非指针 b2 := bytes.NewBuffer([]byte{}) // 指针 b3 := &bytes.Buffer{} // 指针, 等同于 b2 b1.WriteString("abc") b2.WriteString("abc") fmt.Println(b1) // {[97 98 99] 0 0} fmt.Println(b1.String()) // abc fmt.Println(b2) // abc 原因: *Buffer 有方法 String(), Buffer 没有 String() 方法. fmt.Println(b1), 就是 fmt 将 b1 按普通结构体进行输出: 分别输出各项 fmt.Println(b1.String()), 调用了 *Buffer 的 String() 方法 fmt.Println(b2), 自动调用 *Buffer 的 String() 方法 参考自 stackoverflowgin-middleware-注意事项
1. gin middleware 如果要中止后面中间件及所有程序的执行, 需要使用 c.Abort() + return 其中 Abort 会中止其后的中间件及页面处理程序, 而不会中止当前中间件函数内的余下程序, 使用 return 来中止当前中间件内后部的程序 func RejectMethodsExceptGet() gin.HandlerFunc { rejectMethods := map[string]struct{}{ "POST": {}, "DELETE": {}, "PUT": {}, "PATCH": {}, } return func(c *gin.Context) { if _, exist := rejectMethods[c.Request.Method]; exist { c.AbortWithStatusJSON(403, gin.H{ "err_msg": "invalid method", }) return } c.Next() } } 2. 中间件 Use 需要写在路由注册之前, 否则将不对之前注册的路由起作用 r := gin.New() r.Use(RejectMethodsExceptGet()) r.GET("/test", func(c *gin.Context) { example := c.MustGet("example").(string) // it would print: "12345" log.go-routine-使用外部变量问题
for i := 0; i < 10; i++ { go func() { fmt.Println(i) } } time.Sleep(time.Second) // 10,10,10,10,... 使用 go vet 检查 // 修改 for i := 0; i < 10; i++ { go func() { i2 := i fmt.Println(i2) } } // 或者(推荐) for i := 0; i < 10; i++ { go func(i int) { fmt.Println(i) }(i) } time.Sleep(time.Second) 参考 https://www.jianshu.com/p/e5f328819d4bsupervisor-unix----tmp-supervisor-sock-no-such-file
[root@iZm5e09hymnzdmgx3964zgZ etc]# cat -n supervisord.conf | grep /tmp -- 22 [unix_http_server] 23 ;file=/tmp/supervisor.sock ; the path to the socket file 24 file=/var/run/supervisor.sock ; the path to the socket file -- 45 [supervisord] 46 ;logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log 47 logfile=/var/log/supervisord.log ; main log file; default $CWD/supervisord.log -- 50 loglevel=info ; log level; default info; others: debug,warn,trace 51 ;pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid 52 pidfile=/var/run/supervisord.pid ; supervisord pidfile; default supervisord.middleware-gin-contrib-cors-在-301-时失效
背景: gin 配置了路由 router.GET("/api/users") , 添加了 cors 中间件, 但是访问 /api/users/ 时, 会返回 301 + cros 错误 原因: gin 默认打开 “RedirectTrailingSlash”, 表示自动添加(或删除) “/” 并作 301 跳转, 这时候还未进入 middleware, 所以 cors 中间件所添加的 header 不会出现在返回头中. 中间件其它现象: c.Header("before-next": "can-be-show") // 会写入到返回头 c.next() c.Header("after-next": "won't be returned") // 不会出现在返回头中 解决办法: 在 gin 路由中同时添加 带 / 和不带 / 的路由, 工作量大, 且 ugly ❌ 使用 nginx 在 go-web 程序外部直接全部带上 cors 头 ✅json-Unmarshal-如何获取-null
对于如下 json 和 struct, 会将 gender 解析为 false, 而实际上应为 nil, 则需要 将 struct 中的 bool 类型转为 *bool 类型 { "name": "Jim Green", "age": 15, "gender": null } type Student struct { Name string `json:"name"` Age int `json:"age"` Name bool `json:"gender"` } 因为在 go 中指针不可以进行运算, 只能引用 对于 *bool 类型的变量, 不能直接赋值 如 var gender *bool *gender = true // panic: runtime error: invalid memory address or nil pointer dereference 而应该对非指针类型赋值, 再引用指针 var gender *bool tempGender := true gender = &tempGendergo-通用-http-client-请求头
参考stackoverflow: adding-a-default-http-header-in-go package main import ( "fmt" "net/http" "time" ) const accessToken = "MY_DEMO_TOKEN" type MyRoundTripper struct { r http.RoundTripper } func (mrt MyRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { r.Header.Add("Authorization", "Bearer: "+accessToken) return mrt.r.RoundTrip(r) } func main() { client := &http.Client{ Timeout: time.Second * 10, Transport: MyRoundTripper{r: http.DefaultTransport}, } fmt.Println(client.Get("http://google.com/")) }go-自定义-struct-转-json
需求: 从 api 获取到 json, 本地 unmarshal 为 struct 后, 以另外的 json tag marhsal 为 json 字符串 type Student struct { Name string `json:"name"` Age int `json:"age"` } strIn := `{ "stu_name": "Jim Green", "age": 14 }` // to json strOut := `{ "name": "Jim Green", "age": 14 }` 使用到的方法 UmarshalJOSN / MarshalJSON 方法一: 通过中间 struct 变量的匿名嵌套 struct embedding (注意防止无限循环使用 alias) package main import ( "encoding/json" "fmt" ) type Student struct { Name string `json:"name"` Age int `json:"age"` } func (s *Student) UnmarshalJSON(data []byte) error { type Alias Student aux := &struct { *Alias StuName string `json:"stu_name"` }{ Alias: (*Alias)(s), } if err := json.go-判断-https-ssl-证书是否过期
package main import ( "crypto/tls" "fmt" "time" ) func main() { conn, err := tls.Dial("tcp", "blog.umesh.wtf:443", nil) if err != nil { panic("Server doesn't support SSL certificate err: " + err.Error()) } err = conn.VerifyHostname("blog.umesh.wtf") if err != nil { panic("Hostname doesn't match with certificate: " + err.Error()) } expiry := conn.ConnectionState().PeerCertificates[0].NotAfter fmt.Printf("Issuer: %s\nExpiry: %v\n", conn.ConnectionState().PeerCertificates[0].Issuer, expiry.Format(time.RFC850)) } 参考自 freecodecamp删除文件夹中的node_modules子文件夹
package main import ( "fmt" "io" "io/fs" "os" "path" "path/filepath" ) func main() { if len(os.Args) == 1 { panic("Enter a file name") } src := os.Args[1] var pathList []string err := filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { if err != nil { return err } if info.IsDir() && info.Name() == "node_modules" { return filepath.SkipDir } if info.IsDir() { return nil } path = filepath.ToSlash(path) pathList = append(pathList, path) return nil }) if err !
Recent Posts
Tags
- apache 4
- axios 1
- benchmark 1
- c 1
- canvas 1
- centos 3
- channel 1
- crontab 1
- css 2
- docker 4
- fail2ban 1
- frp 1
- gin 1
- github 1
- go 26
- goaccess 1
- goroutine 1
- http 1
- https 1
- jetbrains 1
- jquery 1
- js 2
- linux 20
- mermaid 1
- mysql 10
- nginx 3
- node 1
- php 43
- prisma 1
- react 8
- server 1
- ssh 2
- tarojs 1
- tcp/ip 1
- token 1
- ubuntu 1
- ufw 1
- unit-test 1
- vmware 1
- vscode 1
- vue 12
- yum 1
- 域名 3
- 安全 2
- 微信 3
- 算法 3