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)。