ETCD TTL
func main() {
// 创建 etcd 客户端
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
fmt.Println("Error connecting to etcd:", err)
return
}
defer cli.Close()
// 设置 TTL (单位为秒)
ttl := int64(10) // 例如 10 秒
resp, err := cli.Grant(context.TODO(), ttl)
if err != nil {
fmt.Println("Error creating lease:", err)
return
}
// 使用 Lease ID 进行 Put 操作
_, err = cli.Put(context.TODO(), "my-key", "my-value", clientv3.WithLease(resp.ID))
if err != nil {
fmt.Println("Error putting key with lease:", err)
return
}
fmt.Println("Key with TTL successfully set.")
}
gRPC UnaryInterceptor
func unaryInterceptor(
ctx context.Context,
req any,
info *googleGrpc.UnaryServerInfo,
handler googleGrpc.UnaryHandler,
) (any, error) {
// 打印被调用的方法名
fmt.Println("Called method:", info.FullMethod)
// 打印传入的请求参数
fmt.Printf("Request: %+v\n", req)
fmt.Printf("Meta: %+v\n", util.GetReqInfoFromCtx(ctx))
// 调用实际的 handler
response, err := handler(ctx, req)
if err != nil {
fmt.Println("err: ", err)
}
return response, err
}
isRunningTest
// isRunningTest 確認是否在跑測試
func isRunningTest() bool {
return flag.Lookup("test.v") != nil
}
GIN dto validator
package validator
import (
"encoding/json"
"errors"
"io"
"net/http"
"reflect"
"sync"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
const (
MB = 1 << 20
maxBody = 5 * MB
)
var srcCache sync.Map // reflect.Type -> srcInfo
type srcInfo struct{ form, uri, validate bool }
type Binder interface {
Validate(*gin.Context) error
}
func infoOf(t reflect.Type) srcInfo {
if v, ok := srcCache.Load(t); ok {
return v.(srcInfo)
}
var s srcInfo
seen := map[reflect.Type]bool{} // 在遞迴外層,所有層級共用
var scan func(reflect.Type)
scan = func(t reflect.Type) {
for isWrapper(t.Kind()) {
t = t.Elem()
}
if t.Kind() != reflect.Struct || seen[t] {
return
}
seen[t] = true
for f := range t.Fields() {
if _, ok := f.Tag.Lookup("form"); ok {
s.form = true
}
if _, ok := f.Tag.Lookup("uri"); ok {
s.uri = true
}
if _, ok := f.Tag.Lookup("binding"); ok {
s.validate = true
}
scan(f.Type)
}
}
scan(t)
srcCache.Store(t, s)
return s
}
func isWrapper(k reflect.Kind) bool {
switch k {
case reflect.Pointer, reflect.Slice, reflect.Array, reflect.Map:
return true
}
return false
}
func Bind[T any](c *gin.Context) (*T, error) {
req := new(T)
// 有 body 才解 JSON
if c.Request.ContentLength != 0 && c.ContentType() == binding.MIMEJSON {
body := http.MaxBytesReader(c.Writer, c.Request.Body, maxBody)
if err := json.NewDecoder(body).Decode(req); err != nil && !errors.Is(err, io.EOF) {
return nil, err
}
}
info := infoOf(reflect.TypeFor[T]())
// 有 query 才映射
if info.form && c.Request.URL.RawQuery != "" {
if err := binding.MapFormWithTag(req, c.Request.URL.Query(), "form"); err != nil {
return nil, err
}
}
// 有 path 參數才映射
if info.uri && len(c.Params) > 0 {
m := make(map[string][]string, len(c.Params))
for _, p := range c.Params {
m[p.Key] = []string{p.Value}
}
if err := binding.MapFormWithTag(req, m, "uri"); err != nil {
return nil, err
}
}
// 有 binding tag 才驗證
if info.validate {
if err := binding.Validator.ValidateStruct(req); err != nil {
return nil, err
}
}
// 有實作才呼叫
if v, ok := any(req).(Binder); ok {
if err := v.Validate(c); err != nil {
return nil, err
}
}
return req, nil
}
func MustBind[T any](c *gin.Context) (*T, bool) {
req, err := Bind[T](c)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return nil, false
}
return req, true
}
tools
benchstat
go install golang.org/x/perf/cmd/benchstat@latest
deadcode
go install golang.org/x/tools/cmd/deadcode@latest
httpstat
- It’s like curl -v, with colours.
go get github.com/davecheney/httpstat
jsonnet
- This an implementation of Jsonnet in pure Go
go get github.com/google/go-jsonnet/cmd/jsonnet
migrate
go install -tags 'mysql,sqlite,sqlite3' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
protobuf
go install google.golang.org/protobuf/cmd/protoc-gen-go@lastest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@lastest
go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
gosec
- Golang security checker
go get -u github.com/securego/gosec/cmd/gosec
govulncheck
go install golang.org/x/vuln/cmd/govulncheck@latest
vegeta
- HTTP load testing tool and library
go get -u github.com/tsenart/vegeta
dasel
- Select, put and delete data from JSON, TOML, YAML, XML and CSV files with a single tool. Supports conversion between formats and can be used as a Go package.
brew install dasel
go install github.com/tomwright/dasel/v2/cmd/dasel@master
hey
- HTTP load generator, ApacheBench (ab) replacement, formerly known as rakyll/boom
brew install hey
slides
- Terminal based presentation tool
brew install slides
go install github.com/maaslalani/slides@latest
gokart
- A static analysis tool for securing Go code
go install github.com/praetorian-inc/gokart@latest
structslop
- structslop is a static analyzer for Go that recommends struct field rearrangements to provide for maximum space/allocation efficiency.
go install -v github.com/orijtech/structslop/cmd/structslop@v0.0.8
go get github.com/orijtech/structslop/cmd/structslop
dive
- A tool for exploring each layer in a docker image
brew install dive
go get github.com/wagoodman/dive
sttr
- cross-platform, cli app to perform various operations on string
go install github.com/abhimanyu003/sttr@latest
gentool
- Gen Tool is a single binary without dependencies can be used to generate structs from database
go install gorm.io/gen/tools/gentool@latest
wire
go install github.com/google/wire/cmd/wire@latest
ko
- Build and deploy Go applications
go install github.com/google/ko@latest
Talisman
A tool to detect and prevent secrets from getting checked in
brew install talisman
array
package main
import (
"fmt"
)
func main() {
a := [5]int{1, 2, 3, 4, 5}
t := a[3:4:4]
fmt.Println(t[0])
}
- A. 3
- B. 4
- C. compilation error
Answer
Try it
B
channel
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 1000)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
}()
go func() {
for {
a, ok := <-ch
if !ok {
fmt.Println("close")
return
}
fmt.Println("a: ", a)
}
}()
close(ch)
fmt.Println("ok")
time.Sleep(time.Second * 100)
}
Answer
Try it
ok
panic: send on closed channel
channel1
package main
import (
"fmt"
)
func main() {
c := make(chan int)
close(c)
val, _ := <-c
fmt.Println(val)
}
Answer
Try it
0
context
package main
import (
"context"
"fmt"
)
func f(ctx context.Context) {
context.WithValue(ctx, "foo", -6)
}
func main() {
ctx := context.TODO()
f(ctx)
fmt.Println(ctx.Value("foo"))
}
- A. -6
- B. 0
- C.
<nil> - D: panic
Answer
Try it
C
context1
package main
import(
"fmt"
"encoding/json"
"context"
)
func main() {
data, _ := json.Marshal(context.WithValue(context.Background(), "a", "b"))
fmt.Println(string(data))
}
Answer
Try it
{"Context":{}}
defer
package main
import (
"fmt"
)
func main() {
defer_call()
}
func defer_call() {
defer func() { fmt.Println("1") }()
defer func() { fmt.Println("2") }()
defer func() { fmt.Println("3") }()
panic("4")
}
Answer
Try it
3
2
1
panic: 4
defer1
package main
import (
"fmt"
)
type Person struct {
age int
}
func main() {
person := &Person{28}
defer fmt.Println(person.age)
defer func(p *Person) {
fmt.Println(p.age)
}(person)
defer func() {
fmt.Println(person.age)
}()
person.age = 29
}
Answer
Try it
29
29
28
defer2
package main
import (
"fmt"
)
type Person struct {
age int
}
func main() {
person := &Person{28}
defer fmt.Println(person.age)
defer func(p *Person) {
fmt.Println(p.age)
}(person)
defer func() {
fmt.Println(person.age)
}()
person = &Person{29}
}
Answer
Try it
29
28
28
defer3
package main
import (
"fmt"
)
var a bool = true
func main() {
defer func() {
fmt.Println("1")
}()
if a == true {
fmt.Println("2")
return
}
defer func() {
fmt.Println("3")
}()
}
Answer
Try it
2
1
defer4
package main
import "fmt"
type temp struct{}
func (t *temp) Add(elem int) *temp {
fmt.Print(elem)
return &temp{}
}
func main() {
tt := &temp{}
defer tt.Add(1).Add(2)
tt.Add(3)
}
- A. 132
- B. 123
- C. 312
- D. 321
Answer
Try it
A
goroutine
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int)
go fmt.Println(<-ch1)
ch1 <- 5
time.Sleep(1 * time.Second)
}
- A. 5
- B. deadlock
- C. compilation error
Answer
Try it
B
interface
package main
import (
"fmt"
)
type People interface {
Show()
}
type Student struct{}
func (stu *Student) Show() {}
func live() People {
var stu *Student
return stu
}
func main() {
if live() == nil {
fmt.Println("AAAAAAA")
} else {
fmt.Println("BBBBBBB")
}
}
Answer
Try it
BBBBBBB
interface1
package main
import (
"fmt"
)
type People interface {
Speak(string) string
}
type Student struct{}
func (stu *Student) Speak(think string) (talk string) {
if think == "love" {
talk = "You are a good boy"
} else {
talk = "hi"
}
return
}
func main() {
var peo People = Student{}
think := "love"
fmt.Println(peo.Speak(think))
}
Answer
Try it
compilation error
cannot use Student{} (value of type Student) as People value in variable declaration: Student does not implement People (method Speak has pointer receiver)
interface2
package main
import "fmt"
type T1 struct {
String func() string
}
func (T1) Error() string {
return "T1.Error"
}
type T2 struct {
Error func() string
}
func (T2) String() string {
return "T2.String"
}
var t1 = T1{String: func() string { return "T1.String" }}
var t2 = T2{Error: func() string { return "T2.Error" }}
func main() {
fmt.Println(t1.Error(), t1.String())
fmt.Println(t2.Error(), t2.String())
fmt.Println(t1, t2)
}
Answer
Try it
T1.Error T1.String
T2.Error T2.String
T1.Error T2.String
interface3
package main
import "fmt"
func main() {
var p [100]int
var m any = [...]int{99: 0}
fmt.Println(p == m)
}
Answer
Try it
true
iota
package main
import "fmt"
const (
x = iota
_
y
z = "zz"
k
p = iota
)
func main() {
fmt.Println(x, y, z, k, p)
}
Answer
Try it
0 2 zz zz 5
iota1
package main
import "fmt"
const (
a = iota
b = iota
)
const (
name = "name"
c = iota
d = iota
)
func main() {
fmt.Println(a, b, c, d)
}
Answer
Try it
0 1 1 2
json
package main
import (
"encoding/json"
"fmt"
)
type AutoGenerated struct {
Age int `json:"age"`
Name string `json:"name"`
Child []int `json:"child"`
}
func main() {
jsonStr1 := `{"age": 14,"name": "potter", "child":[1,2,3]}`
a := AutoGenerated{}
json.Unmarshal([]byte(jsonStr1), &a)
aa := a.Child
fmt.Println(aa)
jsonStr2 := `{"age": 12,"name": "potter", "child":[3,4,5,7,8,9]}`
json.Unmarshal([]byte(jsonStr2), &a)
fmt.Println(aa)
}
- A. [1 2 3] [1 2 3]
- B. [1 2 3] [3 4 5]
- C. [1 2 3] [3 4 5 6 7 8 9]
- D. [1 2 3] [3 4 5 0 0 0]
Answer
Try it
B
json1
package main
import (
"encoding/json"
"fmt"
"time"
)
func main() {
t := struct {
time.Time
N int
}{
time.Date(2020, 12, 20, 0, 0, 0, 0, time.UTC),
5,
}
m, _ := json.Marshal(t)
fmt.Printf("%s", m)
}
- A. {“Time”:“2020-12-20T00:00:00Z”,“N”:5}
- B. “2020-12-20T00:00:00Z”
- C. {“N”:5}
- D.
<nil> - E. 其他
Answer
Try it
B