Go 语法
约 861 字大约 3 分钟
2024-05-19
初始化
- map, channel, slice 推荐使用 make // a := make([]string, 0)
- 指针推荐使用new // p = new(Persion)
- map 必须初始化
默认值
- bool fasle
- numbers 0
- string ""
- pointer nil
- slice nil
- map nil
- channel interface function nil
- struct 不是nil 默认值为具体字段默认值
defer
defer 语句会将其后面跟随的语句进行延迟处理
var mu sync.Mutex
mu.Lock()
defer mu.Unlock()
error panic, recover
error
// error
func a() (int, error) {
return 0, errors.New("this is an error")
}
func main() {
if _, err := a(); err != nil {
fmt.Println(err);
}
}
panic
// panic
panic("this is an panic") // panic 会导致程序退出 例如: 依赖服务未启用时调用
recover
// recover
func a() (int, error) {
defer func() {
if r := recover(); r != nil { // 捕捉 panic
fmt.Println("recover if a: ", r)
}
}()
panic("this is an panic")
}
type
// 类型别名
type MyInt = int
var i MyInt = 0
fmt.Printf("%T\r\n", i) // int
// 自定义类型
type MyInt int
var i MyInt = 0
fmt.Printf("%T\r\n", i) // main.MyInt
// 扩展方法 不能直接在int上扩展
func (mi MyInt) toString() string {
return strconv.Itoa(int(mi))
}
var i MyInt = 0;
i.toString() // "0"
结构体
type Persion struct {
name string
age int
}
func main() {
p1 := Persion{ "zhangsan", 18 } // 必须初始化全部参赛
p2 := Persion{ // 可以只初始化部分参数
name: "zhangsan",
age: 18,
}
persions := []Persion{
{"zhang", 18}, // 可以省略前面的Persion
{
age: 18,
},
}
p1.name = ""
// 匿名结构体
a := struct {
name string
age int
}{
"name",
18,
}
// 匿名嵌套
type Student struct {
Persion // 初始化和普通嵌入一样, 但可以tg .name直接操作
score float32
}
}
// 结构体定义方法
// func (s structType) funcName (param1 ...) (return1 ...) { } # 和上面扩展一样
func (p Persion) persion() { // 值传递
fmt.Println("name: %s, age: %d\r\n", p.name, p.age)
}
func (p *Persion) setAge(age int) { // 引用传递
p.age = age
}
interface
type MyWriter interface {
Writer(string) error
}
type MyCloser interface {
Closer() error
}
type fileWriter struct {
filePath string
}
type databaseWriter struct {
// ...
}
func (fw *fileWriter) Writer(_ string) error {
fmt.Println("writer string to file")
return nil
}
func (wc *databaseWriter) Writer(_ string) error {
fmt.Println("writer string to database")
return nil
}
type MyWriterAndCloser struct {
MyWriter
}
func main() {
var mw MyWriter = &MyWriterAndCloser{
&fileWriter{},
}
_ = mw.Writer("")
}
类型转换
var a interface{} = 1
value, ok := a.(int)
if ok {
fmt.Println(value)
}
单元测试
*_test.go
func TestAdd(t *testing.T) {
re := add(1, 2)
if re != 3 {
t.Error("add failed.")
}
}
// 性能测试
func BenchmarkStringBuilder(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var builder strings.Builder
for j := 0; j < 10000; j++ {
builder.WriteString(strconv.Itoa(j))
}
_ = builder.String()
}
b.StopTimer()
}
sync.WaitGroup 等待goroutine执行结束
var gw sync.WaitGroup
for i := 0; i < 10; i++ {
gw.Add(1)
go func() {
defer gw.Done( )
// ...
}()
}
gw.Wait()
lock
互斥锁
var lock sync.Mutex // 不可复制 不用手动初始化 结构体会自动初始化
lock.Lock()
defer lock.Unlock()
total += 1
// 对于+1 可以用 atomic.AddInt32(&total, 1)代替
读写锁
var lock sync.RWMutex
lock.Lock() // 写
defer lock.Unlock()
lock.RLock() // 对
defer lock.RUnlock()
channel
channel 是多线程安全的
var msg chan string = make(chan string, 2) // >0 有缓冲 ==0 无缓冲
msg <- "hello"
msg <- "world"
close(msg)
str := <-msg // hello
for item := range msg {
fmt.Println(item)
}
var msg chan string = make(chan string, 2) // 双向channel
var send chan<- string = msg // 只写 // 不能转回去(chan string)(send)
var read <-chan string = msg // 只对
select
ch1 := make(chan int, 1)
ch2 := make(chan int, 1)
ch1 <- 1
ch2 <- 2
select { // 某一个分支就绪了就执行该分支 如果多个都就绪了,随机执行一个,防止现饿
case <-ch1:
fmt.Println("ch1")
case <-ch2:
fmt.Println("ch2")
case <-time.NewTimer(time.Second).C: // 1s后返回的channel
fmt.Println("timer expired")
}
context
func main() {
gw.Add(1)
ctx, cancel := context.WithCancel(context.Background())
// context.WithValue
valueCtx := context.WithValue(ctx, "traceId", "12345")
// context.WithTimeout 主动超时
// ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
go cpuInfo(valueCtx)
time.Sleep(5 * time.Second)
cancel()
gw.Wait()
}
func cpuInfo(ctx context.Context) {
defer gw.Done()
_ := valueCtx("traceId") // 取值
for {
select {
case <-ctx.Done():
fmt.Println("退出")
return
default:
time.Sleep(time.Second)
fmt.Println("cpu info")
}
}
}