go语言new和make
1.new
func new(Type) *Type
内建函数,内建函数 new 用来分配内存,它的第一个参数是一个类型,它的返回值是一个指向新分配类型默认值的指针!
2.make
func make(Type, size IntegerType) Type
内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数是一个类型,跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型
Slice: 第二个参数 size 指定了它的长度,它的容量和长度,你可以传入第三个参数来指定不同的容量值,但必须不能比长度值小。
比如 make([]int, 0, 10)
***尤其注意append切片时,如果长度和容量指定一个数,那么追加后则在末尾,并不在首部,看下面实例
package main
import "fmt"
func main() {
// 追加到了末尾
mkSlice = append(mkSlice, 10)
fmt.Println(mkSlice)
// make切片 并追加到切片头部
// 那么需要把长度设为0,即没有切片内容
// 长度为0,容量为5
mkSlice2 := make([]int, 0, 5)
fmt.Println(mkSlice2)
// 追加到了末尾
mkSlice2 = append(mkSlice2, 10)
fmt.Println(mkSlice2)
}
结果:
[0 0 0 0 0]
[0 0 0 0 0 10]
[]
[10]
其他切片案例使用
package main
import "fmt"
func main() {
//s1 := make([]int, 5, 6)
//fmt.Println(s1)
//fmt.Println(len(s1))
//fmt.Println(cap(s1))
// 数组
s2 := [3]int{1, 2, 3}
s3 := s2 // 赋值 ,内存不同
fmt.Println(s2, s3)
fmt.Printf("%p\n", &s2)
fmt.Printf("%p\n", &s3)
fmt.Println(s2 == s3) // 注意区别,值比较
s2[0] = 1000
fmt.Println(s2, s3) //[1000 2 3] [1 2 3]
fmt.Println(&s2 == &s3) // 注意区别,取得的是地址
fmt.Printf("%v\n", s2)
fmt.Printf("%v\n", s3)
fmt.Println("==================")
// 切片
s4 := []int{1, 2, 3}
s5 := s4 // 引用s4里的值指向一个地方
fmt.Println(s4, s5)
s4[0] = 1000
fmt.Println(s4, s5) //[1000 2 3] [1000 2 3]
fmt.Println(&s4 == &s5) // 注意区别,取得的是变量的地址
fmt.Printf("%p\n", s4)
fmt.Printf("%p\n", s5)
fmt.Println("===============")
//test()
fmt.Printf("\n", )
// make切片
mkSlice := make([]int, 5)
fmt.Println(mkSlice)
// 追加到了末尾
mkSlice = append(mkSlice, 10)
fmt.Println(mkSlice)
// make切片 并追加到切片头部
// 那么需要把长度设为0,即没有切片内容
// 长度为0,容量为5
mkSlice2 := make([]int, 0, 5)
fmt.Println(mkSlice2)
// 追加到了末尾
mkSlice2 = append(mkSlice2, 10)
fmt.Println(mkSlice2)
}
func test() {
slice0 := []string{"a", "b", "c", "d", "e"}
fmt.Println("\n~~~~~~元素遍历~~~~~~")
for _, ele := range slice0 {
fmt.Print(ele, "-")
ele = "7" // ele值改变不了切片中的值
}
fmt.Println("\n========")
fmt.Println(slice0)
fmt.Println("\n~~~~~~索引遍历~~~~~~")
for index := range slice0 {
fmt.Print(slice0[index], " ")
}
fmt.Println("\n~~~~~~元素索引共同使用~~~~~~")
for index, ele := range slice0 {
fmt.Print(ele, "-", slice0[index], " ")
}
fmt.Println("\n~~~~~~修改~~~~~~")
for index := range slice0 {
slice0[index] = "9"
}
fmt.Println(slice0)
}
Map: 根据 size 大小来初始化分配内存,不过分配后的 map 长度为 0,如果 size 被忽略了,那么会在初始化分配内存时分配一个小尺寸的内存
map案例
package main
import "fmt"
func main() {
//// 随机数种子
//rand.Seed(time.Now().UnixNano())
//
//scoreMap := make(map[string]int, 200)
//for i := 0; i < 100; i++ {
// key := fmt.Sprintf("student%02d", i)
// scoreMap[key] = rand.Intn(100)
//}
//
//fmt.Println(scoreMap)
//
//// 排序map的key
//// 按字符串排序
//keys := make([]string, 0, 100)
//for key := range scoreMap {
// keys = append(keys, key)
//}
//
//sort.Strings(keys)
//// 打印
//for _, key := range keys {
// fmt.Println(key, scoreMap[key])
//}
var mapSlice = make([]map[string]string, 1, 3)
for index, value := range mapSlice {
fmt.Printf("===index:%d value:%v\n", index, value)
}
// 初始化
cur := map[string]string{"name":"hahah","1212":"3333"}
mapSlice = append(mapSlice, cur)
for index, value := range mapSlice {
fmt.Printf("!!!index:%d value:%v\n", index, value)
}
//fmt.Println("after init")
//// 对切片中的map元素进行初始化
//mapSlice[0] = make(map[string]string, 10)
//mapSlice[0]["name"] = "jadeshu"
//mapSlice[0]["password"] = "123456"
//mapSlice[0]["address"] = "北京"
//for index, value := range mapSlice {
// fmt.Printf("index:%d value:%v\n", index, value)
//}
//a := make([]int, 10)
//fmt.Println(a) //[0 0]
//a[1] = 20
//fmt.Println(a)
//fmt.Println(len(a)) //2
//fmt.Println(cap(a)) //10
// 端口:【address,ip】
//info := make(map[int]map[string]string, 3)
//info[8080] = make(map[string]string,4)
//info[8080]["address"] = "上海"
//info[8080]["ip"] = "127.0.0.1"
//info[6060] = make(map[string]string,4)
//info[6060]["address"] = "北京"
//info[6060]["ip"] = "192.168.0.101"
//fmt.Println(info)
//
//testInfo:= &map[int]map[string]string{
// 6000:{
// "address":"香港",
// "ip":"127.0.0.1",
// },
// 7000:{
// "address":"武汉",
// "ip":"127.0.0.1",
// },
//}
//
//fmt.Println(testInfo)
}
Channel: 管道缓冲区依据缓冲区容量被初始化。如果容量为 0 或者忽略容量,管道是没有缓冲区的
总结
new 的作用是初始化一个指向类型的指针(*T),make 的作用是为 slice,map 或 chan 初始化并返回引用(T)。