美文网首页
go语法学习笔记

go语法学习笔记

作者: hypercode | 来源:发表于2021-08-19 17:18 被阅读0次

    1.是一种静态强类型、编译型语言,语法与C相近,功能更丰富:内存安全,GC(垃圾回收),结构形态及并发计算
    2.go get 下载的包放在哪里呢?
    用go env 命令 发现 gopath 为E:\goapp
    在子目录中找到了 E:\goapp\src\github.com
    3.{ 不能在单独的行上
    4.在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。
    如果你打算将多个语句写在同一行,它们则必须使用 ; 人为区分,但在实际开发中我们并不鼓励这种做法。
    5.Go 语言的字符串可以通过 + 实现连接
    6.a, b, c := 5, 7, "abc"
    7.空白标识符 _ 也被用于抛弃值,如值 5 在:, b = 5, 7 中被抛弃。 实际上是一个只写变量,你不能得到它的值
    8.可以通过 &i 来获取变量 i 的内存地址,例如:0xf840000040(每次的地址都可能不一样)。值类型的变量的值存储在栈中。
    内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。
    9.import的库,如果没有用到,会报错?
    10.大括号({)不能够换行放置。
    11.if判断式和for循环不需要以小括号包覆起来。
    12.Go亦有内置gofmt工具,能够自动整理代码多余的空白、变量名称对齐、并将对齐空格转换成Tab。
    13.go1.8时,相同业务场景下的GC时延已经可以从go1.1的数秒,控制在1ms以内
    14.格式化输出

    var i int
        var f float64
        var b bool
        var s string
        fmt.Printf("%v %v %v %q\n", i, f, b, s)
    

    15.Print("\n ") = Println(" ") print:将信息显示在命令窗口中,输出光标定位在最后一个字符之后。 printf:将信息进行格式化显示在命令窗口中,输出光标定位在最后一个字符之后。 println:将信息显示在命令窗口中,输出光标换行定位在下一行开头。

    16.var ( // 这种因式分解关键字的写法一般用于声明全局变量
    a int
    b bool
    )

    17.g, h := 123, "hello" 这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。
    如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误。
    全局变量是允许声明但不使用的。

    18.常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

    19.枚举,用常量实现

    const (
        Unknown = 0
        Female = 1
        Male = 2
    )
    

    20.常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过

    21.关于iota

    const (
                a = iota   //0
                b          //1
                c          //2
                d = "ha"   //独立值,iota += 1
                e          //"ha"   iota += 1
                f = 100    //iota +=1
                g          //100  iota +=1
                h = iota   //7,恢复计数
                i          //8
        )
        fmt.Println(a,b,c,d,e,f,g,h,i)结果:0 1 2 ha ha 100 100 7 8
    
    func main() {
       var a int = 4
       var b int32
       var c float32
       var ptr *int
    
       /* 运算符实例 */
       fmt.Printf("第 1 行 - a 变量类型为 = %T\n", a );
       fmt.Printf("第 2 行 - b 变量类型为 = %T\n", b );
       fmt.Printf("第 3 行 - c 变量类型为 = %T\n", c );
    
       /*  & 和 * 运算符实例 */
       ptr = &a     /* 'ptr' 包含了 'a' 变量的地址 */
       fmt.Printf("a 的值为  %d\n", a);
       fmt.Printf("*ptr 为 %d\n", *ptr);
    }
    
    结果:
    第 1 行 - a 变量类型为 = int
    第 2 行 - b 变量类型为 = int32
    第 3 行 - c 变量类型为 = float32
    a 的值为  4
    *ptr 为 4
    

    23.条件语句
    select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行

    24.函数闭包

    func getSequence() func() int {
       i:=0
       return func() int {
          i+=1
         return i  
       }
    }
    
    func main(){
       /* nextNumber 为一个函数,函数 i 为 0 */
       nextNumber := getSequence()  
    
       /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
       fmt.Println(nextNumber())
       fmt.Println(nextNumber())
       fmt.Println(nextNumber())
       
       /* 创建新的函数 nextNumber1,并查看结果 */
       nextNumber1 := getSequence()  
       fmt.Println(nextNumber1())
       fmt.Println(nextNumber1())
    }
    结果为:1 2 3 1 2
    

    25.函数方法

    import (
       "fmt"  
    )
    
    /* 定义结构体 */
    type Circle struct {
      radius float64
    }
    
    
    func main()  { 
       var c Circle
       fmt.Println(c.radius)
       c.radius = 10.00
       fmt.Println(c.getArea())
       c.changeRadius(20)
       fmt.Println(c.radius)
       change(&c, 30)
       fmt.Println(c.radius)
    }
    func (c Circle) getArea() float64  {
       return c.radius * c.radius
    }
    // 注意如果想要更改成功c的值,这里需要传指针
    func (c *Circle) changeRadius(radius float64)  {
       c.radius = radius
    }
    
    // 以下操作将不生效
    //func (c Circle) changeRadius(radius float64)  {
    //   c.radius = radius
    //}
    // 引用类型要想改变值需要传指针
    func change(c *Circle, radius float64)  {
       c.radius = radius
    }
    

    26.全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑

    27.切片是对数组的抽象。
    Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

    1. range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
    func main() {
        //这是我们使用range去求一个slice的和。使用数组跟这个很类似
        nums := []int{2, 3, 4}
        sum := 0
        for _, num := range nums {
            sum += num
        }
        fmt.Println("sum:", sum)
        //在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
        for i, num := range nums {
            if num == 3 {
                fmt.Println("index:", i)
            }
        }
        //range也可以用在map的键值对上。
        kvs := map[string]string{"a": "apple", "b": "banana"}
        for k, v := range kvs {
            fmt.Printf("%s -> %s\n", k, v)
        }
        //range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
        for i, c := range "go" {
            fmt.Println(i, c)
        }
    }
    

    29.Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
    Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
    如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对。

    func main() {
        var countryCapitalMap map[string]string /*创建集合 */
        countryCapitalMap = make(map[string]string)
    
        /* map插入key - value对,各个国家对应的首都 */
        countryCapitalMap [ "France" ] = "巴黎"
        countryCapitalMap [ "Italy" ] = "罗马"
        countryCapitalMap [ "Japan" ] = "东京"
        countryCapitalMap [ "India " ] = "新德里"
    
        /*使用键输出地图值 */
        for country := range countryCapitalMap {
            fmt.Println(country, "首都是", countryCapitalMap [country])
        }
    
        /*查看元素在集合中是否存在 */
        capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
        /*fmt.Println(capital) */
        /*fmt.Println(ok) */
        if (ok) {
            fmt.Println("American 的首都是", capital)
        } else {
            fmt.Println("American 的首都不存在")
        }
    }
    以上实例运行结果为:
    
    France 首都是 巴黎
    Italy 首都是 罗马
    Japan 首都是 东京
    India  首都是 新德里
    American 的首都不存在
    
    func main() {
            /* 创建map */
            countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}
    
            fmt.Println("原始地图")
    
            /* 打印地图 */
            for country := range countryCapitalMap {
                    fmt.Println(country, "首都是", countryCapitalMap [ country ])
            }
    
            /*删除元素*/ delete(countryCapitalMap, "France")
            fmt.Println("法国条目被删除")
    
            fmt.Println("删除元素后地图")
    
            /*打印地图*/
            for country := range countryCapitalMap {
                    fmt.Println(country, "首都是", countryCapitalMap [ country ])
            }
    }
    以上实例运行结果为:
    
    原始地图
    India 首都是 New delhi
    France 首都是 Paris
    Italy 首都是 Rome
    Japan 首都是 Tokyo
    法国条目被删除
    删除元素后地图
    Italy 首都是 Rome
    Japan 首都是 Tokyo
    India 首都是 New delhi
    

    Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。

    import (
        "fmt"
    )
    
    type Phone interface {
        call()
    }
    
    type NokiaPhone struct {
    }
    
    func (nokiaPhone NokiaPhone) call() {
        fmt.Println("I am Nokia, I can call you!")
    }
    
    type IPhone struct {
    }
    
    func (iPhone IPhone) call() {
        fmt.Println("I am iPhone, I can call you!")
    }
    
    func main() {
        var phone Phone
    
        phone = new(NokiaPhone)
        phone.call()
    
        phone = new(IPhone)
        phone.call()
    
    }
    

    (1) 不需使用括号将条件包含起来

    (2) 大括号{}必须存在,即使只有一行语句

    (3) 左括号必须在if或else的同一行

    (4) 在if之后,条件语句之前,可以添加变量初始化语句,使用;进行分隔

    (5) 在有返回值的函数中,最终的return不能在条件语句中

    if statement; condition {  
    }
    

    协程则完全不是这么一回事,协程是不切换的,执行完协程A,再执行协程B
    协程切换的条件有两个

    该协程主动要求切换给其他协程
    该协程执行时遇到堵塞,比如在等待 IO 读数据,或者读channel时陷入等待,这样就会被CPU强行切换到其他协程

    相关文章

      网友评论

          本文标题:go语法学习笔记

          本文链接:https://www.haomeiwen.com/subject/jijabltx.html