• 【Golang】关于Go中一些常用的知识介绍


    一、哪些类型可以作为map的key ?

    1、可比较的类型都可以作为map key

    • boolean 布尔值

    • numeric 数字 包括整型、浮点型,以及复数

    • string 字符串

    • pointer 指针 两个指针类型相等,表示两指针指向同一个变量或者同为nil

    • channel 通道 两个通道类型相等,表示两个通道是被相同的make调用创建的或者同为nil

    • interface 接口 两个接口类型相等,表示两个接口类型 的动态类型 和 动态值都相等 或者 两接口类型 同为 nil

    • structs、arrays 只包含以上类型元素

    2、不能作为map key 的类型包括

    • slices

    • maps

    • functions

    3、下面针对几种类型的比较做举例说明

    package main
    
    import (
    	"fmt"
    )
    
    type Orange struct {
    	Host string
    	Port int
    }
    
    func main() {
    	
    	// 指针
    	orange1 := Orange{}
    	orange2 := Orange{}
    
    	op11 := &orange1
    	op12 := &orange1
    	op2 := &orange2
    
    	fmt.Println("op11 == op12 :", op11 == op12) // true
    	fmt.Println("op11 == op2 :", op11 == op2) // false
    
    	// 通道
    	ch1 := make(chan int, 1)
    	ch2 := ch1
    	ch3 := make(chan int, 1)
    
    	fmt.Println("ch1 == ch2 :", ch1 == ch2) // true
    	fmt.Println("ch1 == ch3 :", ch1 == ch3) // false
    
    	// 结构体
    	orange3 := Orange{}
    	orange4 := Orange{}
    	orange5 := Orange{"host001", 22}
    
    	fmt.Println("orange3 == orange4 :", orange3 == orange4) // true
    	fmt.Println("orange3 == orange5 :", orange3 == orange5) // false
    
    	// 数组
    	a1 := [1]int{0}
    	a2 := [1]int{0}
    
    	fmt.Println("a1 == a2 :", a1 == a2) // true
    }

    输出结果

    op11 == op12 : true
    op11 == op2 : false
    ch1 == ch2 : true
    ch1 == ch3 : false
    orange3 == orange4 : true
    orange3 == orange5 : false
    a1 == a2 : true 

    二、关于make及切片slice、映射map详解

    内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),使用make来创建slice,map,chanel说明如下:

    1、make 创建slice

    make([]Type, len, cap)

    cap可以省略。当cap省略时,默认等于len。此外cap >= len >= 0的条件必须成立。例如,创建一个len和cap均为10的int型slice。

    // 长度为5,容量为10的slice,slice中的元素是int
    var slice_ []int = make([]int,5,10)
    fmt.Println(slice_)
    
    var slice_1 []int = make([]int,5)
    fmt.Println(slice_1)
    
    var slice_2 []int = []int{1,2}
    fmt.Println(slice_2)
    

    用第三个参数设置该slice的容量(即底层数组的长度)。如果能够预足容量,那么在slice中数据增长的过程中不需要更换底层数组(附带拷贝过程),这样效率更高。

    2、make 创建 map

    make(map[keyType] valueType, size)

    keyType表示map的key类型,valueType表示map的value类型。size是一个整型参数,表示map的存储能力,该参数可省略。

    var m_ map[string]int = make(map[string]int)
    m_["one"] = 1
    fmt.Println(m_)
    
    var m map[string]int = map[string]int{"1":1}
    m["2"] = 2
    fmt.Println(m)  

    根据 size 大小来初始化分配内存,不过分配后的 map 长度为 0,如果 size 被忽略了,那么会在初始化分配内存时分配一个小尺寸的内存

    3、make 创建chanel

    make(chan Type, size)

    使用make创建channel,第一个参数是channel类型。size表示缓冲槽大小,是一个可选的大于或等于0的整型参数,默认size = 0。当缓冲槽不为0时,表示通道是一个异步通道。

    package main
     
    import "fmt"
     
    func main() {
    	demo := make(chan int, 10)
    	fmt.Println("demo:", demo)
    	// output: demo: map[]
    	fmt.Println("len(demo):", len(demo))
    	// output: len(demo): 0
    	fmt.Println("cap(demo):", cap(demo))
    	// output: cap(demo): 10
    
    }

    4、关于new函数

    Go提供内建函数new

    func new(Type) *Type
    

    它只接受一个参数,这个参数是一个类型,分配好内存后,返回一个指向该类型内存地址的指针。同时请注意它同时把分配的内存置为零,也就是类型的零值。

    func main() {
     var i *int
     i=new(int)
     *i=10
     fmt.Println(*i)
    }
    

    它返回的永远是类型的指针,指向分配类型的内存地址

    5、注意事项 make和new的区别

    • new的作用是初始化一个指向类型的指针(*T)。使用new函数来分配空间,传递给new函数的是一个类型,不是一个值。返回的是指向这个新分配的零值的指针。(内存置为零)

    • make的作用是为slice、map或chan初始化并返回引用(T)。make仅仅用于创建slice、map和channel,并返回它们的实例。(非零值)

    • make返回的还是这三个引用类型本身;而new返回的是指向类型的指针

    • new不常用,通常都是采用短语句声明以及结构体的字面量达到我们的目的

    • make函数是无可替代的,二者都是内存的分配堆上

    6、映射map

    • map是一种数据结构,用于存储一系列无序的键值对,类似java的HashMap

    • 通过散列表实现,使用两个数据结构来存储数据,一个数组用于选择桶的散列键的高八位值,可以区分每个键值属于哪个桶;另一个字节数组,用于存储键值对

    • 创建方式make(map[keyType] valueType, cap),其中keyType表示键类型,valueType表示值类型,cap表示初始存储能力

    //创建了一个键类型为string、值类型为PersonInfo
    myMap = make(map[string] PersonInfo) 
    //也可以选择是否在创建时指定该map的初始存储能力,创建了一个初始存储能力为100的map.
    myMap = make(map[string] PersonInfo, 100) 
    //创建并初始化map的代码.
    myMap = map[string] PersonInfo{ 
      "1234": PersonInfo{"1", "Jack", "Room 101,..."}, 
    } 

    三、关于数组和切片的区别 ? 

    • Slice和数组类似,也是表示一个有序元素,但这个序列的长度可变,具有动态长度特性;

    • 切片是指针类型,数组是值类型;

    • 数组的长度是固定的,而切片不是(切片可以看成动态的数组);

    • 切片比数组多一个容量(cap)属性;

    • 切片的底层是数组;

    • 多个切片可以指向同一个底层数组,实现了内存共享

    • 切片本身是一个只读对象,其工作机制类似数组指针的一种封装

    以下代码输出什么?如果去掉注释又输出什么?

    package main
    
    import (
       "fmt"
    )
    
    func main() {
       a := [2]int{5, 6}
       b := [2]int{5, 6}
    
       if a == b {
          fmt.Println("equal")
       } else {
          fmt.Println("not equal")
       }
    
       /*
          if a[:] == b[:] {
              fmt.Println("equal")
          } else {
              fmt.Println("not equal")
          }
       */
    }

    输出:equal,去掉注释提示: invalid operation: a[:] == b[:] (slice can only be compared to nil)

    go语言中数组和切片的区别

    所以,a、b定义的是数组类型,数组对比是相同的,但是,a[:]、b[:]是切片,切片之间不能进行等值判断,只能和nil判断

  • 相关阅读:
    从键盘输入10个数,计算出正数和负数的个数。
    浏览器允许的并发请求资源数 优化
    strict 严格模式
    AMD 和 CMD 的区别
    Canvas
    visual filters 滤镜 ie
    ie 如何判断正在执行的脚本
    async
    富文本编辑器
    检测CSS属性 是否支持
  • 原文地址:https://www.cnblogs.com/chenpingzhao/p/16325398.html
Copyright © 2020-2023  润新知