Administrator
Administrator
发布于 2026-03-09 / 0 阅读
0
0

golang不常用的特性

变量

    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 //十六进制


评论