• Golang 类型定义总结手册| 面试最基础


    变量 var

    • 关键字是 var ,定义后须被调用
    • 支持多个同时定义
    • 支持使用 := 缺省定义

    变量定义(声明)

    //使用var 关键字 进行变量定义 : var + 变量名 + 变量类型
    //Var name type
    var aa int = 10
    //var name 省略类型
    var aa = 10
    // 多个进行定义,也可省略类型
    var Mon, Tues, Wed, Thur, Fri, Sat, Sun int
    var (
        Monday    int
        Tuesday   int
        Wednesday int
        Thursday  int
        Friday    int
        Saturday  int
        Sunday    int
    )
    // 使用 := 快捷定义,但":=" 结构不能在函数外使用
     var aa := 10
     //多个定义
     aa, bb :=10, '10'
     //声明但可不使用
     aa,_ := 10, '10'
    

    变量调用

    //变量调用分为 局部变量 和 全局变量
    package main
    
    //import
    import (
    	"fmt"
    )
    
    //全局变量定义 aa ss
    var (
    	aa = 3
    	ss = "kkk"
    )
    
    //局部变量定义
    func variableZeroValue() {
    	var a int
    	var s string
    	//fmt.Println(a, s)
    	fmt.Printf("%d %q 
    ", a, s)
    }
    func main() {
    	//fmt.Println("helloworld")
    	variableZeroValue()
    	}
    

    常量 const

    • 关键字为 const, 可不被调用
    • 枚举类型 iota
    • 常量不可改变

    常量定义

    //const name type
    //const name
    //:=
    //多常量
    const(
    aa = 1
    bb =2
    )
    //使用iota, 从0开始,iota 自增被打断,须显式恢复
    const (
    		b = 1 << (10 * iota)
    		kb
    		mb
    		gb
    	)
    

    常量调用

    • 常量使用与变量相似 ,故不赘述
    • 与c语言不同,常量不能通过指针进行强制更改

    数组 arr

    • 在Go语言中数组是固定长度的数据类型,它包含相同类型的连续的元素,这些元素可以是内建类型,像数字和字符串,也可以是结构类型,元素可以通过唯一的索引值访问,从0开始。
    • 使用 var 关键字

    数组定义

    //定义 长度是5的arr
    var arr [5]int
    //定义并初始化
    var arr [5]int = [5]int{1,2,3,4,5}
    //快速定义
    arr := [5]int{1,2,3,4,5}
    //不知长度
    arr := [...]int{1,2,3,4}
    //部分初始化, 其他位置初始化为0
    arr := [5]int{1:1,3:4}
    

    调用

    package main
    import "fmt"
    
    func main() {
        array := [2]int{}
        fmt.Printf("数组长度:%d,数组容量:%d
    ", len(array), cap(array))
    }
    //数组长度:2,数组容量:2
    

    切片 Slice

    • "动态数组" ,长度不固定,可以追加 append (name, 5)
    • 通过内部指针和相关属性应用数组片段
    • type, len, cap 为Slice三个属性, 如果slice == nil 则len,cap均为零

    定义

    //定义一个切片,不用大小
    var name []int
    //定义并初始化
    var aa []int = []int{1,2,3}
    var bb = []int{1,2,3}
    //通过内置函数make 进行定义 make (type, len, cap)
    var aa []int = make([]int, 3)
    var aa = make([]int, 3)
    var aa = make([]int, 3, 3)
    aa := make([]int, 3)
    //通过切数组得到 arr := [5]int{1,2,3,4,5}
    aa := arr[:len(arr)-1]
    

    调用

    切片拷贝,使用copy() 函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠。

    package main
    import "fmt"
    func main() {    
    	var a = []int{1, 2, 3, 4, 5}
        b := []int{100, 200}
        copy(a, b)
        fmt.Println(a, b)
        }
    

    运行结果:

    [100 200 3 4 5]  [100 200]
    

    容器 Map

    • key- value 表
    • 无序,散列表hash完成
    • 可使用内置函数delete(m, "key"), 不可以在map上使用cap()方法。

    定义

    //声明
    var m map[int]string
    //声明并初始化
    var m map[int]string {1;"1",2;'2'}
    //通过make 创建
    var m1 = make(map[int]string, 10)
    m2 = make(map[int]string, 10)
    

    调用

    //增
    m[3] = "3"
    //删,删除操作,如果 key 不存在,不会出错
    delete(m, "3")
    //改
    m[1] ='2'
    //查
    if _, ok = m[3]; ok{
     fmt.Println("find it")
    }
    //长
    len := len(m)
    

    管道 Channel

    • 看成管道, 可单双向使用, chan 定义

    • 无缓冲的与有缓冲channel有着重大差别,那就是一个是同步的 一个是非同步的。 比如

      无缓冲chan:ch1:=make(chan int)

      有缓冲chan:ch2:=make(chan int,1)

      无缓冲: ch1<-1 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-ch1 接手了这个参数,那么ch1<-1才会继续下去,要不然就一直阻塞着。

      有缓冲: ch2<-1 则不会阻塞,因为缓冲区大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

      缓冲区是内部属性,并非类型构成要素。

    • 普通 channel 可以隐式转为只读channel或只写channel,反过来则不行

    • 内置函数 len() 返回未被读取的缓冲元素数量,使用内置函数 cap() 返回缓冲区大小

    • 使用内置函数 close() 进行关闭 chan,向已经关闭的 channel 发送数据会引发 panic 错误。

    定义

    //使用chan 定义
    var aa chan int
    var aa chan string
    var aa chan map[int]string
    //make 定义 
    var aa = make(chan int) //无缓冲
    var aa = make(chan int, 10) //有缓冲
    //只读 
    var aa <-chan int
    var aa = make(<-chan int, 10)
    //只写
    var aa chan<- int
    var aa = make(chan<-int, 10) 
    

    调用

    //开
    var aa = make(chan int, 3)
    //放
    aa <- 1
    //关
    close(aa)
    

    指针

    • *(取值符) 来获取指针所指向的内容 , &(取地址符)来获取该变量的指针。
    • 不可加减乘除,Go语言是不允许两个指针类型进行转换的
    • 空指针 nil
    • unsafe.Pointer 类型用于表示任意类型的指针

    定义

    //使用var 进行
    var p *int
    //使用:= 定义
    var str string
    p := &str
    //指针变量的指针
    var **p  int
    //time.Time (一个结构体)值的指针 
    var t *time.Time
    

    结构体

    • 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

    • struct 特点
      1、用来自定义复杂数据结构
      2、struct里面可以包含一个或多个字段(属性)
      3、struct类型可以定义方法,注意和函数的区分
      4、struct类型是值类型
      5、struct类型可以嵌套
      6、结构体是用户单独定义的类型,不能和其他类型进行强制转换
      7、Go中的struct没有构造函数,一般可以使用工厂模式来解决这个问题
      8、我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化
      9、访问结构体成员, 用 "." 来连接,格式为:"结构体.成员名"

    定义

    //全局或函数内定义类型
    type bight int64
    //定义新类型,不能同时嵌入某一类型和其指针类型(名字相同)
    type moreType struct{
    	linux string
    	win string
    	debin string
    }
    type lin stuct{
    	*linux
    }
    
    //声明struct结构的时候,在属性的右侧用小米点括起来的内容叫标签(Tag),在转换成其它数据格式的时候,会使用其中特定的字段作为键值。例如转成json格式
    	user := &User{UserId: 1, UserName: "helloworld"}
    	json_user, _ := json.Marshal(user)
    	fmt.Printf("struct User echo : %v
    ", string(json_user))
    
    	user_tag := &UserTag{UserId: 1, UserName: "helloworld"}
    	json_user_tag, _ := json.Marshal(user_tag)
    	fmt.Printf("struct UserTag echo : %v
    ", string(json_user_tag))
    

    函数

    定义

    //无参数
    func funName(){
    }
    //有参数
    func funName(x, y int){
    }
    //一返回值
    func funName(x, y int) int{
    }
    //多返回
    fun funNmame(x,y int)(ret int, err error){
    }
    //只有类型
    fun funNmame(int, int)(int, error){
    }
    
    

    1、Go语言函数中的参数不支持默认值。

    2、无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

    3、map、slice、chan、指针、interface默认以引用的方式传递。

    4、函数的可变参数只能有一个,且必须是最后一个。

    5、在参数赋值时可以不用用一个一个的赋值,可以直接传递一个数组或者切片,特别注意的是在参数后加上“…”即可。

    特殊函数

    //匿名函数
    var sum func(int, int) int = func(x, y int)int{return x+y}
    sum := func(x, y int)int{return x+y}
    
    //递归函数
    func factorial(i int) int {
        if i <= 1 {
            return 1
        }
        return i * factorial(i-1)
    }
    

    延时调用 defer 注意

    • 当defer被声明时,参数被实时解析
    • defer执行顺序为先进后出。
    • defer 可以读取有名返回值
  • 相关阅读:
    BZOJ2330 SCOI2011糖果
    BZOJ 3812主旋律
    模板更新 扩展卢卡斯
    BZOJ4556 HEOI2016字符串
    CodeForces700E Cool Slogans
    Atcoder Contest069F:Flag
    计算几何模板(更新中......)
    BZOJ4003 JLOI2015城池攻占
    BZOJ3772精神污染
    HDU5919 SequenceⅡ
  • 原文地址:https://www.cnblogs.com/wxiaote/p/11763228.html
Copyright © 2020-2023  润新知