Go语言中文文档-1Go基础
Go于2009年由谷歌推出。
Init函数和main函数
Init函数
用于程序执行前初始化包变量
每个包可以多个,同一个包多个init执行顺序无明确定义
按照包导入依赖关系决定不同包初始化函数执行顺序
不能被调用,main函数执行前自动被调用
与main函数异同
相同点:
都不能有参数和返回值,都是go程序自动调用。
不同点:
init可以用于不同包,可定义多个。
main只能用于main包,只能定义一个。
命令
go env打印Go语言环境
go run编译运行命令源码文件
go get从互联网下载代码包依赖包编译和安装
go build编译源码文件、代码包及依赖包
go install编译并安装代码包及依赖包
go doc + Go实体 查看文档
go test测试go编写的程序
go list列出代码包信息
运算符
自增自减不是运算符
下划线
下划线在import中
import _ "./hello"
表示程序引用包中所有init函数,并不能通过包名调用包中其他函数。
下划线在代码中
表示忽略这个变量,如果用变量不使用,编译器报错。
变量和常量
变量
变量声明后必须使用
标准声明:var name string
批量声明:var (
a string
b int
c bool
d float32
)
类型推导: var sex = 1
函数内部短变量声明:n := 100
匿名变量:x, _ = foo()不占命名空间,不分配内存
常量
const pi = 3.1415
const (
a = 1
b
)
上述b == a
iota
常量计数器,只能在常量表达式使用。
基本类型
整型
int64对应C语言long
多行字符串
定义时必须使用反引号字符
字符串常用操作
分割:strings.Split
判断是否包含:strings.Contains
前后缀判断:strings.HasPrefix, strings.HasSuffix
子串位置:strings.Index(), strings.LastIndex()
join操作:strings.Join(a[]string, sep string)
byte rune
byte: ASCII类型
rune:UTF-8
修改字符串
先转换成[]rune, []byte完成后再转换为string
类型转换
go只有强制类型转换,无隐式类型转换
数组Array
var a[5] int和var a [10]int是不同类型
指针数组 [n]* T, 数组指针 *[]T
数组初始化:var arr = [...]int{1, 2, 3, 4, 5, 6}
var arr1 = [5]int{2: 100, 4: 200}
var arr2 = [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
len, cap都返回数组长度。
切片Slice
切片是引用类型,自身是结构体,值拷贝传递。
创建切片:var s1 []int
s2 := []int{1, 2, 3}
var s3 []int = make([]int, len, cap)省略cap则cap = len
s1 := []int{0, 1, 2, 3, 8:100}
data := [][]int{
[]int{1, 2, 3},
[]int{100, 200},
[]int{11, 22, 33, 44},
}
d := [5]struct {
x int
}{}
c = append(s1, s2...)
超出slice.cap限制,就会重新分配底层数组。通常两倍容量重新分配。
数组或切片转字符串: strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",", -1)
slice底层实现
切片数据结构
切片通过指针引用底层数组,切片是只读对象,是对类似数组指针的封装。
空切片和nil切片
空切片:var slice []int一般表示一个空集合
nil切片:slice := make([]int, 0)函数发生异常时返回
slice := []int{}
上述区别,一个指针指向内存地址,一个指针为nil
扩容策略
如果切片容量小于1024,两被扩容到新地址,不改变原数组
如果切片容量超过1024,1.25倍扩容
扩容针对原来容量,不针对原数组长度。
指针
Go指针不能偏移与运算
new和make
Go语言对引用类型变量,使用时要为之分配内存,对值类型,使用时默认分配好了内存空间。
new
a := new(int)
指针作为引用类型,声明后必须用new初始化后才可以为指针指向的值赋值。
make
使用slice、map、channel时,都需要使用make进行初始化。
new、make区别
make返回引用类型本身, new返回指向类型的指针。
make用于slice、map、channel初始化,而new用于类型内存分配
Map
map是无序的kv数据结构,是引用类型,初始化后可以使用。
定义: map[KeyType]ValueType
分配内存:make(map[KeyType]ValueType, [cap])
判断某个键是否存在:value, ok := map[key]
if ok {
} else {
}
遍历:for k, v := range m {
}
for k := range m {
}
遍历顺序不一定是添加顺序
删除键值对:delete(m, key)
Go中Map的实现原理
通过桶的方式解决冲突问题,key,value分开存储以节省内存空间,每个桶存放元素有最大数量,超过最大数量则通过overflow获取链表上的下一个桶。
结构体
自定义类型:
type MyInt int
类型别名:
type byte = uint8
自定义类型和类型别名的区别
自定义类型后通过新类型定义变量,输出变量类型为新类型。
类型别名后,仍然输出原类型。
匿名结构体:
var user struct{Name string; Age int}
创建指针类型结构体:
var p2 = new(person)
取结构体的地址实例化
p3 := &person{}
使用值的列表初始化:
p8 := &person {
1,
"aa",
}
上述方式必须初始化所有字段,必须与声明方式一致,不能和键值初始化混用。
构造函数
func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}
p9 := newPerson("pprof.cn", "测试", 90)
方法和接收者
方法:作用于特定类型变量的函数
方法属于特定的类型,函数不属于任何类型。
什么时候应该使用指针类型接收者?
需修改接受者值,接受者拷贝代价高,方法使用的接受者一致性(如都是指针接受者)。
Go中任意类型都可以拥有方法,但我们不能给别的包的类型定义方法。
结构体字段的可见性
结构体中字段大写开头表示可公开访问,小写表示仅在当前结构体包中访问。
结构体与JSON序列化
序列化
data, err := json.Marshal(c)
反序列化
err = json.Unmarshal([]byte(str), c1)
结构化标签
Tag: 结构体的元信息
key1:"value1" key2:"value2"
实现map有序输出
点击查看代码
package main
import (
"fmt"
"sort"
)
func main() {
map1 := make(map[int]string, 5)
map1[1] = "www.topgoer.com"
map1[2] = "rpc.topgoer.com"
map1[5] = "ceshi"
map1[3] = "xiaohong"
map1[4] = "xiaohuang"
sli := []int{}
for k, _ := range map1 {
sli = append(sli, k)
}
sort.Ints(sli)
for i := 0; i < len(map1); i++ {
fmt.Println(map1[sli[i]])
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话