1:确认Go版本信息
C:\Users\Administrator>go version
go version go1.18.1 windows/amd64
2:查看Go环境
C:\Users\Administrator>go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=E:\go\path\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=E:\go\path
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=E:\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=E:\go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.18.1
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set GOWORK=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\ADMINI~1\AppData\Local\Temp\go-build643624193=/tmp/go-build -gno-record-gcc-switches
1:定义变量
# var 变量名 类型 = 表达式# 注:在这里表达式其实就是在内存开辟的空间存了这个表达式# 方法1
package main
import (
"fmt"
)
func main() {
var name string = "zhangsan"
var age int = 18
var ok bool = true
fmt.Println(name, age, ok) # 打印变量
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 true
# 方法2(最常用)
package main
import (
"fmt"
)
func main() {
name := "zhangsan"
age := 18
ok := true
fmt.Println(name, age, ok)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 true
# 方法3
package main
import (
"fmt"
)
func main() {
var name string
var age int
var ok bool
name = "zhangsan"
age = 18
ok = true
fmt.Println(name, age, ok)
}
# 声明的全局变量
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 true
# 定义多个同类型变量
package main
import (
"fmt"
)
func main() {
var name, age string
var ok bool
name, age = "zhangsan", "18"
fmt.Println(name, age, ok)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 false
# 定义多个变量
package main
import (
"fmt"
)
func main() {
var (
name string
age int
ok bool
)
name = "zhangsan"
age = 18
ok = true
fmt.Println(name, age, ok)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 true
# 注:声明/导入即使用,引入包或声明变量等等的必须使用,否则会报错!!!
5.2:常量
变量与常量的区别:
变量:值可以随意改变
常量:不可以改变的值
# 定义一个常量
package main
import (
"fmt"
)
func main() {
const name = "zhansgan"
fmt.Println(name)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhansgan
# 尝试修改常量
package main
import (
"fmt"
)
func main() {
const name = "zhansgan"
name = "lisi"
fmt.Println(name)
}
# 运行
PS E:\goland\demo> go run .\main.go
# command-line-arguments
.\main.go:9:2: cannot assign to name (untyped string constant "zhansgan")
# 测试var进行修改
package main
import (
"fmt"
)
func main() {
var age = 100
age = 200
fmt.Println(age)
}
# 运行
PS E:\goland\demo> go run .\main.go
200
# 在变量下修改的值是OK的,这里要注意的是修改数据必须和源数据是同一类型,否则会报错
# 批量定义常量
package main
import (
"fmt"
)
func main() {
const (
name string = "zhangsan"
age int = 18
ok bool = true
)
fmt.Println(name, age, ok)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan 18 true
# 注:在同一个代码块内,不管是变量和常量,中间的名称是不可以重复的,只能选择其一
5.3:fmt包
1:fmt.Println # 一个打印会换行的方法
2:fmt.Print # 是一个不会换行的打印
3:fmt.Printf # 是一个格式化输出的打印
# 第一个Demo(无法换行打印)
package main
import "fmt"
func main() {
fmt.Print("123")
fmt.Print("456")
}
# 运行
PS E:\goland\demo> go run .\main.go
123456
# 第二个Demo(可换行打印)
package main
import "fmt"
func main() {
fmt.Println("123")
fmt.Println("456")
}
# 运行
PS E:\goland\demo> go run .\main.go
123
456
# 第三个Demo(可以将变量或常量或者其他参数带进打印内)
package main
import "fmt"
func main() {
name := "zhangsan"
fmt.Printf("名称是:%s", name)
}
# 运行
PS E:\goland\demo> go run .\main.go
名称是:zhangsan
# 这里面会有两个常用参数:%s和%d,意思分别是:%s:必修是string类型%d:必须是int类型
和结构体类似,变量命名一般使用驼峰法,首字母根据访问控制原则使用大写或者小写。但是遇到特有名词时,需要遵循以下规则:如果变量为私有,且持有名词为首个单词,则使用小写,如appSerice,若变量类型为bool类型,则名称以Has,Is,Can或Allow开头
# demo如下:
func main() {
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
}
# 错误用法# int8 超出了范围
package main
import "fmt"
func main() {
var a int8 = 4
var b int8 = 128
fmt.Println("a:", a, a)
fmt.Println("a:", b, b)
}
# 运行
PS E:\goland\demo> go run .\main.go
# command-line-arguments
.\main.go:7:15: cannot use 128 (untyped int constant) as int8 value in variable declaration (overflows)
# 正确用法(int8 -128 到 127)
package main
import "fmt"
func main() {
var b int8 = 127
fmt.Println("a:", b, b)
}
# 运行
PS E:\goland\demo> go run .\main.go
a: 127 127
# 其他的int也是同理
9.6.2:reflect.TypeOf查看数据类型
# 判断当前的数据是什么类型
package main
import (
"fmt"
"reflect" # 导包
)
func main() {
var b int8 = 127
fmt.Println(reflect.TypeOf(b)) # 打印并输出类型
}
# 运行
PS E:\goland\demo> go run .\main.go
int8
# 第二种打印方法# 查看类型+查看数据(这里涉及到了%T和%v的使用)# 具体的%+参数:%T:打印类型,%v:打印值,%s:打印字符串,%d:打印数字
package main
import (
"fmt"
)
func main() {
var b int8 = 127
fmt.Printf("%T: %v", b, b) # 这里用到的方法是Printf
}
# 运行
PS E:\goland\demo> go run .\main.go
int8: 127
9.6.3:布尔值
Go语言中以bool类型声明布尔型类型,布尔型其实只有(True;真)或(false:假)两个值。
# 注意:
1:布尔类型便变量默认为false。
2:Go语言中不允许整型强制转换为布尔型
3:布尔型无法参与数值计算,也无法与其他类型转换
# 具体demo如下
package main
import (
"fmt"
"reflect"
)
func main() {
a := true # 这里以最简单的方式取定义每当然也可以用 var a bool = true
fmt.Println(reflect.TypeOf(a))
}
# 运行
PS E:\goland\demo> go run .\main.go
bool
# 查看占用字节数量
package main
import (
"fmt"
"unsafe"
)
func main() {
var a bool = false
fmt.Println(unsafe.Sizeof(a)) # 这里使用到了 unsafe.Sizeof()方法
}
# 我们多定义两个不同的类型来看看效果
package main
import (
"fmt"
"unsafe"
)
func main() {
a := true
b := "张三"
var c int8 = 123
var d int16 = 12345
var e int32 = 123456789
var f int64 = 123456789012345
fmt.Println(a, b, c, d, e, f)
fmt.Println(unsafe.Sizeof(a))
fmt.Println(unsafe.Sizeof(b))
fmt.Println(unsafe.Sizeof(c))
fmt.Println(unsafe.Sizeof(d))
fmt.Println(unsafe.Sizeof(e))
fmt.Println(unsafe.Sizeof(f))
}
# 运行
PS E:\goland\demo> go run .\main.go
true 张三 123 12345 123456789 123456789012345
1
16
1
2
4
8
# 大家可以对应一下
10:字符串
10.1:字符串
Go语言里面的字符串的内部实现是用UTF-8编码,字符串的值为("")双引号中的内容,可以在Go语言的源码中直接添加非ASCII码字符串,如:
name := "zhangsan"
my_name := "张三"
10.2:多行字符串
反引号间换行将被作为字符串中的换行,但是,所有转义字符均无效,文本将被原样输出。如:
package main
import "fmt"
func main() {
name := `zhangsan
lisi
wangwu`
fmt.Println(name)
}
# 运行
PS E:\goland\demo> go run .\main.go
zhangsan
lisi
wangwu
10.3:byte和rune
Go语言中有以下两种字符:
uint8:或者叫byte类型,代表ASCII码的一个类型
rune:代表一个UTF-8字符
1:字符串的底层是一个byte数组,所以可以和byte类型相互转换
2:字符串是不能修改的,字符串是由byte字节组成,所以字符串长度是byte字节的长度
3:rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成
# demo
package main
import "fmt"
func main() {
a := "Hello World"
fmt.Printf("%#v", a[:11])
}
# 运行
PS E:\goland\demo> go run .\main.go
"Hello World"
# 转换其中的值
package main
import "fmt"
func main() {
a := "你好朋友"
a_rune := []rune(a) # 转换类型为数组,然后即可读写
s_go := string(a_rune[:2]) + "Go" # 切片获取原有数据,string方法将byte数组转化成字符串然后进行替换。
fmt.Println(s_go)
}
# 运行
PS E:\goland\demo> go run .\main.go
你好Go
10.4:字符串常用操作
方法
介绍
len(str)
求长度
+ / fmt.Sprintf
拼接字符串
strings.Split
分割
strings.Contains
判断是否包含
strings.HashPrefix / strings.HashSuffix
前缀/后缀判断
strings.Index() / strings.LastIndes()
子串出现的位置
strings.Join(a[]string, sep string)
join操作
10.4.1:len(str)
package main
import "fmt"
func main() {
a := "zhangsan"
fmt.Println(len(a))
}
# 运行
PS E:\goland\demo> go run .\main.go
8
10.4.2:+ (拼接)
package main
import "fmt"
func main() {
a := "你好!"
b := "Golang!"
fmt.Println(a + b)
}
# 运行
PS E:\goland\demo> go run .\main.go
你好!Golang!
10.4.3:strings.Split
# 通过strings.Split()方法将字符串转换成数组
package main
import (
"fmt"
"strings"
)
func main() {
a := "2022-06-23"
arr := strings.Split(a, "-")
fmt.Println(arr)
}
# 运行
PS E:\goland\demo> go run .\main.go
[2022 06 23]
package main
import (
"fmt"
"strings"
)
func main() {
a := "2022-06-23"
arr := strings.Split(a, "-")
fmt.Println(arr[0])
}
# 这样打印应该是2022,运行demo如下
PS E:\goland\demo> go run .\main.go
2022
# 查看它的类型
package main
import (
"fmt"
"strings"
)
func main() {
a := "2022-06-23"
arr := strings.Split(a, "-")
fmt.Printf("%T: %v\n", arr, arr)
}
# 运行demo
PS E:\goland\demo> go run .\main.go
[]string: [2022 06 23]
package main
import "fmt"
func main() {
var a [5]int
fmt.Println(a)
}
# 运行
PS E:\goland\demo> go run .\main.go
[0 0 0 0 0]
# 注意。默认数组里面是有元素的,默认为0# 接下来我们给数组赋值
package main
import "fmt"
func main() {
var a [5]int
a[0] = 1 # 向数组中的索引添加元素
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
fmt.Println(a)
}
# 运行
PS E:\goland\demo> go run .\main.go
[1 2 3 4 5]
# 另一种方式
package main
import "fmt"
func main() {
var a = [...]string{"bj", "sh", "gz", "sz"} # 这里...的意思是让编译器自动识别我们的数组长度
fmt.Println(a)
}
# 运行
PS E:\goland\demo> go run .\main.go
[bj sh gz sz]
# 注意:当你的索引超出了定义的元素个数的时候会报错,数组是不会自增的!
11.2:遍历数组
11.2.1:普通遍历(for)
package main
import "fmt"
func main() {
var a = [...]string{"bj", "sh", "gz", "sz"}
for i := 0; i < len(a); i++ { # 这里的i数组的索引由0开始,当索引数小于数组长度就一直循环,每次循环都+1
fmt.Println(i, a[i]) # 打印每次循环的索引和值
}
}
# 运行
PS E:\goland\demo> go run .\main.go
0 bj
1 sh
2 gz
3 sz
11.2.2:k v 遍历数组(range)
package main
import "fmt"
func main() {
var a = [...]string{"bj", "sh", "gz", "sz"}
for index, value := range a { # 这里range是go自己实现的一个方法,它的输出是两个值,一个是索引一个是值
fmt.Printf("index:%d,value:%s\n", index, value) # 用两个参数来接收数据
}
}
# 运行
PS E:\goland\demo> go run .\main.go
index:0,value:bj
index:1,value:sh
index:2,value:gz
index:3,value:sz
# 注意,这里面的 index value不是一定要用这个的当然了 index也不是一定要打印出来的,可以用以下方法
package main
import "fmt"
func main() {
var a = [...]string{"bj", "sh", "gz", "sz"}
for _, value := range a {
fmt.Printf("value:%s\n", value)
}
}
# 注意:这里的_不是代表不接数据了,他还是会接收数据,但是可以不调用!# 运行
PS E:\goland\demo> go run .\main.go
value:bj
value:sh
value:gz
value:sz
12:切片(Slice)
12.1:切片基础
12.1.1:切片的定义
1:切片是一个拥有相同类型的元素的可变长度的序列
2:它是基于数组类型做的一层封装
3:它非常灵活,支持自动扩容
4:切片是一个引用类型,它的内部结构包含地址,长度和容量
5:声明切片类型基础语法demo如下
var a []string
# a 是切片名称# string 是切片类型
package main
import "fmt"
func main() {
var num []string # //定义一个字符串切片
# // 使用 num和nil比较
fmt.Println(num == nil) # // true
# // 打印num
fmt.Println(num)
var name = []int{} # // 定义一个整型切片并初始化
# // 打印name
fmt.Println(name)
# // 使用name与nil比较
fmt.Println(name == nil) # // false
var c = []bool{false, true} // 定义一个布尔值切片并初始化
# // 打印c
fmt.Println(c)
# // 使用c与nil比较
fmt.Println(c == nil) # // false
}
# 运行以上代码
PS E:\goland\demo> go run .\main.go
true
[]
[]
false
[false true]
false
# 注意:切片是引用类型,不支持直接比较,只能和 nil比较,(与数组比起来,数组是有长度无容量,而切片是有容量可扩展长度)
1:切片与切片之间无法比较,我们不能使用==操作符来判断两个切片是否含有全部相等元素
2:切片唯一合法的比较是与nil对比,一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0
3:但是我们不能说一个长度和容量都为0的切片一定是nil
package main
import "fmt"
func main() {
var a = []string{"北京", "上海", "广州"}
for i := 0; i < len(a); i++ {
fmt.Printf("%s\n", a[i])
}
}
# 运行
PS E:\goland\demo> go run .\main.go
北京
上海
广州
12.2.2:K V遍历
package main
import "fmt"
func main() {
var a = []string{"北京", "上海", "广州"}
for i, v := range a {
fmt.Printf("%d:%s\n", i, v)
}
}
# 相同的,我们用到了range()函数# 运行
PS E:\goland\demo> go run .\main.go
0:北京
1:上海
2:广州
# 当然也适用如下(接收索引但不使用)
package main
import "fmt"
func main() {
var a = []string{"北京", "上海", "广州"}
for _, v := range a {
fmt.Printf("%s\n", v)
}
}
# 运行
PS E:\goland\demo> go run .\main.go
北京
上海
广州
package main
import "fmt"
func main() {
# // 定义一个数据map
info := map[string]string{ # 带入上方的demo可以看到第一个 string代表key的类型,第二个string代表value的类型
"username": "admin",
"password": "123456",
}
fmt.Println(info)
}
# 运行
PS E:\goland\demo> go run .\main.go
map[name:admin passwd:123456]
13.3:map的基本使用
13.3.1:判断某个键是否存在
# 第一种方法
package main
import "fmt"
func main() {
# // 定义一个数据map
info := map[string]string{
"username": "admin",
"password": "123456",
}
# // 判断map中是否存在某个key
v, ok := info["username"] # // 首先定义出要判断的key
if ok { # // 判断key是否为真
fmt.Println(v) # // 若为真,则打印出值
} else {
fmt.Println("not found") # 否则打印"not found"
}
}
# 运行
PS E:\goland\demo> go run .\main.go
admin
# 替换username为"USERNAME"
package main
import "fmt"
func main() {
// 定义一个数据map
info := map[string]string{
"username": "admin",
"password": "123456",
}
// 判断map中是否存在某个key
v, ok := info["USERNAME"]
if ok {
fmt.Println(v)
} else {
fmt.Println("not found")
}
}
# 再次执行
PS E:\goland\demo> go run .\main.go
not found
# 第二种方法
import "fmt"
func main() {
# // 定义一个数据map
info := map[string]string{
"username": "admin",
"password": "123456",
}
# // 判断map中是否存在某个key # // 这里接收参数的ok是一个bool,如果值存在则是true,不存在则是false,它也是判断key的唯一标准 # // 然而第一个是查询key的值本身,第二个是布尔值,就依赖布尔值来判断这个值是否存在!
if _, ok := info["username"]; ok {
fmt.Println("username存在")
} else {
fmt.Println("username不存在")
}
}
13.3.2:delete()函数
1:使用delete()内建函数从map中删除一组键值对,delete()函数的格式:delete(map对象,key)
2:其中:
2.1:map对象表示要删除键值对的map对象
2.2:key表示要删除的键值对的key
package main
import "fmt"
func main() {
info := map[string]string{
"username": "admin",
"password": "123456",
}
# // 将password字段从map中删除
delete(info, "password")
fmt.Println(info)
}
# 运行
PS E:\goland\demo> go run .\main.go
map[username:admin]
13.4:map遍历
13.4.1:k v 遍历
package main
import "fmt"
func main() {
info := map[string]string{
"username": "admin",
"password": "123456",
}
for k, v := range info {
fmt.Printf("%v: %v\n", k, v)
}
}
# 这里和前面我们学到的都是一样的,使用range返回值并使用两个参数收即可# 运行
PS E:\goland\demo> go run .\main.go
username: admin
password: 123456
13.4.2:只读Key
package main
import "fmt"
func main() {
info := map[string]string{
"username": "admin",
"password": "123456",
}
for k := range info {
fmt.Println(k, info[k])
}
}
# 运行
PS E:\goland\demo> go run .\main.go
password 123456
username admin
14:指针
14.1:关于指针
1:搞明白Go语言中指针需要先知道三个概念:指针地址,指针类型,指针取值
1.1:指针地址(&a)
1.2:指针取值(*&a)
1.3:指针类型(&a) ----> *int (改变数据传指针)
2:变量的本质是给存储数据的内存地址起了一个好记的别名
3:比如我们定义一个 a := 10,这个时候可以直接通过a这个变量来读取内存中保存的a这个值
4:在计算机底层a这个变量其实对应了一个内存地址
5:指针也是一个变量,但是它是一种特殊的变量,它存储的数值不是一个普通的数值,而是另一个变量的内存地址
6:Go语言中中的指针操作:&(取地址),*(根据地址取值),记住这两个符号就可以了
package main
import "fmt"
func main() {
a := 10
fmt.Println(&a) # // 获取内存地址
fmt.Printf("%d\n", &a) # // 取指针地址
fmt.Printf("%d\n", *&a) # // 取指针的值
fmt.Printf("%T\n", &a) # // 获取指针类型
}
# 运行
PS E:\goland\demo> go run .\main.go
PS E:\goland\demo> go run .\main.go
0xc0000140a8 # 内存地址
824633802920 # 对应的指针地址
10 # 指针的值
*int # 指针的类型
14.2:&取变量地址
14.2.1:&符取地址操作
package main
import "fmt"
func main() {
var a int = 10
var b = &a
var c = *&a
fmt.Println(a) # // 打印a的值
fmt.Println(b) # // 把a的内存地址赋值给b并打印b的值
fmt.Println(c) # // 从内存地址内取值并赋值给c并打印c的值
}
# 运行
PS E:\goland\demo> go run .\main.go
10
0xc0000140a8
10
14.2.2:b := &a图解
14.3:new和make
14.3.1:执行报错
1:执行下面代码会引起panic,为什么
2:在Go语言对于引用类型的变量,我们在使用时不仅要声明它,还要为它分配内存空间,否则我们的值就无法存储
3:而对于值类型的声明则不需要分配内存空间,是因为它们在声明的时候已默认分配好了内存空间
4:如果要分配内存,就要用到 new和make了
5:Go语言中 new和make是两个内建函数,主要用于分配内存
package main
import "fmt"
func main() {
var info map[string]string
info["name"] = "Zhangsan"
fmt.Println(info)
}
# 这个代码执行报错如下
panic: assignment to entry in nil map
14.3.2:new和make比较
1:new和make是两个内置函数,主要用来创建并分配类型的内存
2:make和new的区别
2.1:make的作用主要用于创建slice,map,和channel等内置函数的数据结构
2.1.1:make只能针对内置数据类型申请内存
2.1.2:返回的是数据值的本身
2.2:new的作用主要为类型申请一片内存空间,并返回指向这片内存空间的指针
2.2.1:new主要是给结构体struct等非内置数据类型申请空间
2.2.2:返回一个指针的数据类型
# 通过make方法申请
package main
import "fmt"
func main() {
a := make([]int, 3, 10)
# // []int:指定切片的类型 # // 3:指定的切片的默认长度3 # // 10:默认的容量10
fmt.Println(a)
fmt.Println(len(a), cap(a))
}
# 运行
PS E:\goland\demo> go run .\main.go
[0 0 0]
3 10
# 通过new方法申请
package main
import "fmt"
func main() {
a := make([]int, 3, 10)
fmt.Println(a)
fmt.Println(len(a), cap(a))
b := new([]int)
fmt.Printf("make:%T ==> new:%T", a, b)
}
# 通过make申请的类型是值类型,但是通过new申请的就是一个指针类型,运行如上代码
PS E:\goland\demo> go run .\main.go
[0 0 0]
3 10
make:[]int ==> new,*[]int
# make初始化的值可以直接append写入数据
package main
import "fmt"
func main() {
a := make([]int, 3, 10)
a = append(a, 1) # // 可以直接使用append写入数据
fmt.Println(a)
fmt.Println(len(a), cap(a))
b := new([]int)
fmt.Println(b)
fmt.Printf("make:%T ==> new:%T", a, b)
}
# 执行如下
PS E:\goland\demo> go run .\main.go
[0 0 0 1]
4 10
make:[]int ==> new:*[]int
# 则new方法不可以,因为指针类型无法直接使用写入,所以我们需要下面的操作
package main
import "fmt"
func main() {
a := make([]int, 3, 10)
a = append(a, 1)
fmt.Println(a)
fmt.Println(len(a), cap(a))
b := new([]int)
*b = append(*b, 1) # 因为类型为指针类型,所以需要使用*b来表示这个类型为指针
fmt.Println(b)
fmt.Printf("make:%T ==> new:%T", a, b)
}
# 运行如下
PS E:\goland\demo> go run .\main.go
[0 0 0 1]
4 10
&[1]
make:[]int ==> new:*[]int
14.3.3:New函数
# 系统数据类型分配空间
package main
import "fmt"
func main() {
# // new 实例化int
age := new(int)
*age = 10
fmt.Println(*age)
# // new实例化切片
slice := new([]int)
*slice = []int{1, 2, 3}
fmt.Println(*slice)
# // new实例化map
userinfo := new(map[string]int)
*userinfo = map[string]int{"name": 1, "age": 2}
(*userinfo)["name"] = 3
fmt.Println(userinfo)
}
# 运行
PS E:\goland\demo> go run .\main.go
10
[1 2 3]
&map[age:2 name:3]
# new 实战内容(自定义类型分配空间)
package main
import "fmt"
func main() {
var s *Student
s = new(Student)
s.Name = "张三"
s.Age = 18
fmt.Println(s)
}
type Student struct {
Name string
Age int
}
# 为自定义类型分配内存# 运行
PS E:\goland\demo> go run .\main.go
&{张三 18}
14.3.4:Make函数
1:make函数也是用于分配内存的,但是和new不同,他只用于chan,map,以及slice的内存创建
2:而且它返回的类型是这三个类型的本身,而不是它们的指针类型
3:因为三个类型都是引用类型,所以就没必要返回它们的指针了
# demo如下
package main
import "fmt"
func main() {
# // 切片长度为1,预留空间为10
a := make([]int, 1, 10)
b := make(map[string]string)
c := make(chan int, 1)
fmt.Println(a, b, c)
}
# 运行
PS E:\goland\demo> go run .\main.go
[0] map[] 0xc00004e070
4:当我们为slice分配内存的时候,应该尽量估算slice的最大长度
5:通过给make传第三个参数的方式来给slice预留好内存空间
6:这样可以避免二次分配内存带来的开销,大大提高程序性能
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 想让你多爱自己一些的开源计时器
· Cursor预测程序员行业倒计时:CTO应做好50%裁员计划
· 大模型 Token 究竟是啥:图解大模型Token
· 如何在 .NET 中 使用 ANTLR4
· 用99元买的服务器搭一套CI/CD系统