变量
var a, b = 10, 20
var (
c = 30
d = 40
)
//一次定义多个变量[3]int像这样定长的称为数组([]int是切片),数组也是值类型
package main
func main() {
var arr [3]int
arr[0] = 1
arr[1] = 2
arr[2] = 3
var arr2 [3]int = arr
var arr3 []int = arr[:] //数组转换成切片
//此时修改arr2和arr3都不会影响arr
}切片是引用类型,但将切片转换为普通数组后就不再是相同引用
package main
func main() {
var arr []int = []int{1, 2, 3}
var arr2 [3]int = [3]int(arr[:3])
arr2[1] = 20 //不会影响arr
var arr3 []int = arr
arr3[1] = 30 //会影响arr
}
切片的内存共享
package main
import (
"fmt"
)
func main() {
var a = []int{1, 2, 3, 4, 5}
var b = a[1:3] //b[0]、b[1] 对应a[1]、a[2]
fmt.Println(&a[1]) //0x1400012c038
fmt.Println(&b[0]) //0x1400012c038
b[0] = 100
fmt.Println(a) // [1 100 3 4 5]
fmt.Println(b) // [100 3]
}
断开共享:
package main
import (
"fmt"
)
func main() {
var a = []int{1, 2, 3, 4, 5} //a的 len=5、cap=5
var b = a[:5] //b的每个成员都和a的成员共享内存,长度和容量都和a相同
b = append(b, 10) //b的len=6、cap=10,b扩容了,b重新分配了内存空间,和a不再共享内存
fmt.Println(&a[0], &b[0]) //0xc0000103c0 0xc0000126e0
}
append + 展开,不会共享:
package main
import (
"fmt"
)
func main() {
var a = []int{1, 2, 3, 4, 5}
var b []int
b = append(b, a...)
fmt.Println(&a[0]) //0x1400001a120
fmt.Println(&b[0]) //0x1400001a150
}
copy()不会共享:
package main
import "fmt"
func main() {
var a = []int{1, 2, 3, 4, 5}
var b []int = make([]int, len(a))
copy(b, a)
fmt.Println(&a[0])
fmt.Println(&b[0])
}
枚举
iota表示0
const (
a = iota
b
c
)
// a b c是默认的int类型,a=0,b=1,c=2 const (
a = iota + 3
b
c
)
// a b c是默认的int类型,从3开始,a=3,b=4,c=5 const (
a = iota
_
b
c
)
// a b c是默认的int类型,用_跳过一个数字,a=0,b=2,c=3 const (
a int64 = iota
b
c
)
//a b c的类型都是int64 const (
a1, a2 int64 = iota, iota + 3
b1, b2
c1, c2
)
//a1=0, a2=3
//b1=1, b2=4常量
const PI = 3.14159
const Name = "Golang"
const ( //一次定义多个常量
A = 1
B = 2
C = 3
)⚠️ 注意:Go 中的常量类型可以是数字、字符串或布尔类型,不能是切片、map、struct 等复合类型。
type别名
可以为基本类型或复杂类型声明一个别名,然后还可以为别名附加成员方法
type MyInt int
func (m MyInt) Call() {
fmt.Println(m)
}
type IntSlice []int
func (m IntSlice) Call() {
fmt.Println(len(m))
}
func main() {
var a MyInt = 10
a.Call() // 10
var b IntSlice = []int{10, 20, 30}
b.Call() //3
}结构嵌套(类似继承)
1.值嵌入与指针嵌入的区别(指针嵌套必须显示初始化)
type A struct {
Name string
}
func (a *A) Call() {
fmt.Println("A Call", a.Name)
}
type B struct {
A
}
type C struct {
*A
}
func main() {
var b B
var c C
b.Call() // A Call
c.Call() // 报错,因为c.A没有初始化,c.A现在是nil,也就不能调用A的Call方法
var c2 C = C{ //显式初始化
A: &A{Name: "A2"},
}
}
2.值类型的嵌入无法调用接收指针类型的成员方法
type Base struct{}
func (Base) Foo() { fmt.Println("Base.Foo") }
func (*Base) Bar() { fmt.Println("Base.Bar") }
type Derived1 struct{ Base }
type Derived2 struct{ *Base }
func main() {
d1 := Derived1{}
d1.Foo() // ✅
// d1.Bar() // ❌ 编译错误:Bar 未被提升
d2 := Derived2{Base: &Base{}}
d2.Foo() // ✅
d2.Bar() // ✅
}switch的fallthrough
强制执行fallthrough的紧挨着的下一个分支(强制执行),fallthrough必须出现在分支的最后一行
package main
import "fmt"
func main() {
a := 2
switch a {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
fallthrough
case 3:
fmt.Println("3")
}
}
字符串
长度:
var a = "12我你ab"
fmt.Println(utf8.RuneCountInString(a)) //6,获取字符数
fmt.Println(len(a)) //10,获取的字节数遍历:
package main
import (
"fmt"
)
func main() {
var a = "12我你ab"
for _, r := range a { //遍历字符
fmt.Println(string(r))
}
fmt.Println("-----")
for i := 0; i < len(a); i++ { //遍历字节
fmt.Println(a[i])
}
}
大量拼接字符串:
package main
import (
"fmt"
"strings"
)
func main() {
var a strings.Builder
a.WriteString("你我123")
a.WriteByte(65) //ASCII 'A'
a.WriteRune(65) //Unicode 'A' rune=int32
a.Write([]byte{66, 67}) //ASCII 'B''C'
fmt.Println(a.Len()) //bytes length
fmt.Println(a.Cap()) //capacity
fmt.Println(a.String())
}
高性能的多次替换:
package main
import (
"fmt"
"strings"
)
func main() {
r := strings.NewReplacer( //定义替换规则。a替换为1,b替换为2,hello替换为hi
"a", "1",
"b", "2",
"hello", "hi",
)
result1 := r.Replace("hello ab")
result2 := r.Replace("AAhello abCC") //规则可以多次使用,区分大小写
fmt.Println(result1) // hi 12
fmt.Println(result2) // AAhi 12BB
}
strconv
所有的base参数支持2~36进制
最常用:
package main
import (
"fmt"
"strconv"
)
func main() {
// A = ASCII
var a string = strconv.Itoa(10) // int to string
b, err := strconv.Atoi("20") // string to int
fmt.Println(a, b, err)
}
Parse系列(字符串 转到 数字、布尔、浮点):
package main
import (
"fmt"
"strconv"
)
func main() {
a, err := strconv.ParseFloat("1.234", 64) //返回类型固定是float64,即使指定32也是float64
b, err := strconv.ParseInt("7b", 16, 64) //表示:"7b"按16进制来解析,返回值是int64
c, err := strconv.ParseInt("123", 10, 64) //表示:"123"按10进制来解析,返回值是int64
d, err := strconv.ParseBool("true") //支持的值有:1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False
e, err := strconv.ParseUint("7b7b", 16, 64) //表示:"7b7b"按16进制来解析,返回值是uint64
}
Format系列(数字、布尔、浮点 转到 字符串)
package main
import (
"fmt"
"strconv"
)
func main() {
//var a string = strconv.FormatInt(123, 10)
//var b string = strconv.FormatInt(123, 16) //解析为16进制,b="7b"
//var c string = strconv.FormatBool(true)
//var d string = strconv.FormatUint(1314, 16)
var e string = strconv.FormatFloat(3.1415926, 'f', -1, 64)
// 'f'表示格式,-1表示小数点后保留几位,-1表示全部保留,64表示float64类型
// 'e'表示科学计数法,'g'表示根据实际情况选择'f'或'e'格式
}
slog包
1.21新增的日志操作
package main
import (
"fmt"
"log/slog"
"os"
)
func main() {
//slog.Error("user login",
// "user_id", 123,
// "ip", "127.0.0.1",
//)
//slog.Info("user login",
// "user_id", 123,
// "ip", "127.0.0.1",
//)
//slog.Debug("user login",
// "user_id", 123,
// "ip", "127.0.0.1",
//)
//slog.Warn("user login",
// "user_id", 123,
// "ip", "127.0.0.1",
//)
//slog.LogAttrs(context.Background(), slog.LevelInfo, "user login", slog.Int64("age", 30), slog.String("username", "admin"))
//输出类似:
//2026/02/06 07:17:13 ERROR user login user_id=123 ip=127.0.0.1
//2026/02/06 07:17:13 INFO user login user_id=123 ip=127.0.0.1
//2026/02/06 07:17:13 WARN user login user_id=123 ip=127.0.0.1
//自定义Handler
opts := &slog.HandlerOptions{
Level: slog.LevelInfo,
AddSource: true, // 显示文件和行号
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { //每个属性在输出前都会调用此函数
fmt.Println(groups, a)
return a
},
}
handler := slog.NewJSONHandler(os.Stdout, opts) //还有TextHandler
logger := slog.New(handler)
slog.SetDefault(logger)
slog.Warn("user login",
"user_id", 123,
"ip", "127.0.0.1",
)
//{"time":"2026-02-06T07:29:33.7107998+08:00","level":"WARN","source":{"function":"main.main","file":"C:/Users/wujinghua/Documents/playgrounds/go-playground/main.go","line":39},"msg":"user login","user_id":123,"ip":"127.0.0.1"}
}
使用第三方依赖,增加一些色彩
//先引入依赖,go get github.com/lmittmann/tint
slog.SetDefault(slog.New(
tint.NewHandler(os.Stdout, &tint.Options{
Level: slog.LevelDebug,
TimeFormat: time.DateTime,
}),
))
slog.Info("test", "username", "admin", "Age", 30)
slog.Info("test", "username", "admin", "Age", 30)
字面量
0b111 //二进制
0777 //八进制
0o777 //八进制
0x777 //十六进制