go一些技巧 - Mon, Jun 15, 2020
go一些技巧
- map第二个返回值 go语言的map有第二个返回值,能够判断在map中key是否存在
value, ok := kv[key]
if !ok {
// do something
}
_
无视其中一个值 使用_
可以无视多个值中的其中几个或全部
_, ok := kv[key]
if !ok {
// do something
}
无视全部值
_, _ := kv[key]
- 在切片后追加元素
var arr []int
arr = append(arr, 1)
- 在切片前追加元素
var arr []int
arr = append([]int{1}, arr...)
- 在切片后追加多个元素
var arr []int
arr = append(arr, []int{1, 2, 3, 4, 5}...)
- 切片越界 不会越界,是空切片
fmt.Println(arr[len(arr):])
会越界
fmt.Println(arr[len(arr)+1:])
会越界
fmt.Println(arr[len(arr)])
- 弃用标记
// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the sql package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// Exec may return ErrSkip.
//
// Deprecated: Drivers should implement ExecerContext instead (or additionally).
type Execer interface {
Exec(query string, args []Value) (Result, error)
}
- BUG标记
// BUG(who): 我是bug说明
- 包注释 单独doc.go文件
package aaa
// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the sql package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// Exec may return ErrSkip.
- Example
文件名
example_xxx_test.go
包名xxx_test
函数名func Example[FuncName][_tag]()
函数尾// Output:
// 文件必须放在 banana包目录下, 名字必须为example_xxx_test.go
// Package banana_test 为banana包的示例
package banana_test
// 此注释将会被展示在页面上
// 此函数将被展示在OverView区域
func Example() {
fmt.Println("Hello OverView")
// Output:
// Hello OverView
}
- UnitTest
文件名
xxx_test.go
包名xxx_test
函数名func Test[FuncName][_tag]()
package server_test
import (
"testing"
"time"
)
func TestServerTimeLayout1(t *testing.T) {
some := time.Now().Format(types.TimeLayout1)
t.Log(some)
}
- BenchmarkTest
文件名
xxx_test.go
包名xxx_test
函数名func Benchmark[FuncName][_tag]()
package types_test
func BenchmarkDataMarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
data := Data{
MsgType: DeviceReq,
Data: []*DeviceS{
{
DeviceID: "abc-123_&%S",
ServiceID: "discrete",
EventTime: "123456",
Data: map[string]interface{}{
"LD_14.XY": "0",
"LD_15.XY": 0,
"LD_16.XY": int64(64),
"LD_17.XY": true,
"LD_18.XY": 123.456,
},
},
},
}
_, err := json.Marshal(data)
if err != nil {
b.FailNow()
}
// fmt.Println("json", string(bytes))
}
}
- 交换数据
func max(a, b int) {
if a > b {
a, b = b, a
}
}
- 函数返回值定义
func swap(a, b int) (max, min int) {
if a > b {
max, min = a, b
} else {
max, min = b, a
}
return
}
- safe delete in range
m := map[string]string{
"1": "one",
"2": "two",
"3": "three",
}
for key, v := range m {
delete(m, key)
}
- switch可以无参
switch {
case a == 3:
case b == 4:
case c == 7:
}
- channel写数据时使用default防lock
select {
case <-quit:
case data<-event:
default:
}
- 无类型结构体
// Info 请求可变更字段
type Info struct {
DNSNames []string `json:"dns"` // 证书认证dns
Duration struct {
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
} `json:"duration"` // 证书有效时间
Path struct {
Servers []struct {
Cert string `json:"cert"`
Key string `json:"key"`
} `json:"servers"`
Clients []struct {
Cert string `json:"cert"`
Key string `json:"key"`
} `json:"clients"`
} `json:"path"`
}
初始化与结构体声明在一起
var opts = struct {
PrintVersion func() `short:"v" long:"version" description:"print the version of the iotx"`
EnableDebug func() `short:"d" long:"debug" description:"enable debug of the iotx"`
}{
PrintVersion: func() {
fmt.Println("Version:", Version)
fmt.Println("BuildTime:", BuildTime)
os.Exit(0)
},
EnableDebug: func() {
logrus.SetLevel(logrus.DebugLevel)
},
}