Go语言学习第一天

package main

import "fmt"

func main() {
   /* 这是我的第一个简单的程序 */
   fmt.Println("Hello, World!")
}
  1. 第一行代码 package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。
  2. 下一行 import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。

    下一行 func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)

     

    文件结构

      文件名与包名没有直接关系,不一定要将文件名与包名定成同一个
      文件夹名与包名没有直接关系,并非需要一致。
      同一个文件夹下的文件只能有一个包名,否则编译报错
      := 声明变量
    v_name := value
    var intVal int 
    intVal =1 
    //类型相同多个变量, 非全局变量
    var vname1, vname2, vname3 type
    vname1, vname2, vname3 = v1, v2, v3
    
    var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断
    
    vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
    
    
    // 这种因式分解关键字的写法一般用于声明全局变量
    var (
        vname1 v_type1
        vname2 v_type2
    )

    变量的生命周期

    全局变量生命周期是程序存活时间
    局部变量是函数存活时间
     
     
        var dic = map[string]int{
            "apple":  1,
            "banana": 2,
        }
        if num, ok := dic["orange"]; ok {
            fmt.Printf("orange num %d\n", num)
        }
        if num, ok := dic["banana"]; ok {
            fmt.Printf("banana num %d\n", num)
        }
    
        switch localStr {
        case "case1":
            fmt.Println("case1")
        default:
            fmt.Println("default")
        }

    数组

     

        var strAry = [10]string{"aa", "bb", "cc", "dd", "ee"}
        //切片初始化
        var sliceAry = make([]string, 0)
        sliceAry = strAry[1:3]
        fmt.Printf("strAry %+v\n", strAry)
        fmt.Printf("sliceAry %+v\n", sliceAry)
              //字典初始化

    //字典初始化
    var dic = map[string]int{
    "apple": 1,
    "watermelon": 2,
    }
    fmt.Printf("dic %+v\n", dic)

     

     循环

    package main
    
    import "fmt"
    
    func main() {
       for i := 0; i < 5; i++ {
          fmt.Printf("current i %d\n", i)
       }
       j := 0
       for {
          if j == 5 {
             break
          }
          fmt.Printf("current j %d\n", j)
          j++
       }
       var strAry = []string{"aa", "bb", "cc", "dd", "ee"} //是的,不指定初始个数也ok
       //切片初始化
       var sliceAry = make([]string, 0)
       sliceAry = strAry[1:3]
       for i, str := range sliceAry {
          fmt.Printf("slice i %d, str %s\n", i, str)
       }
       //字典初始化
       var dic = map[string]int{
          "apple":      1,
          "watermelon": 2,
       }
       for k, v := range dic {
          fmt.Printf("key %s, value %d\n", k, v)
       }
    }

    for rang的坑

    arr := [2]int{1, 2}
    res := []*int{}
    for _, v := range arr {
        res = append(res, &v)  
     }fmt.Println(*res[0],*res[1])  //expect: 1 2 fact: 2 2 
    内部调用还是for循环,初始化会拷贝带遍历的列表(如array,slice,map),然后每次遍历的v都是对同一个元素的遍历赋值。 也就是说如果直接对v取地址,最终只会拿到一个地址,而对应的值就是最后遍历的那个元素所附给v的值。对应伪代码如下
    // len_temp := len(range)
    // range_temp := range
    // for index_temp = 0; index_temp < len_temp; index_temp++ {
    //     value_temp = range_temp[index_temp]
    //     index = index_temp
    //     value = value_temp
    //     original body
    //   }

    解决方案

    //1局部变量拷贝
    for _, v := range arr {//局部变量v替换了v,也可用别的局部变量名
        v1 := v 
        res = append(res, &v1)
    }

     

     
    for k := range arr {
        res = append(res, &arr[k])
    }
    用鹏哥的话就是arr[:] 类似于切片截取,当没有参数的时候,就是截取整个原数组,返回的结果和原切片其实是指向同一个底层数组,指针不同而已。
    总结一下,就是切片结构体指针类型,指向原底层数组,返回一个新的指针。

    对大数组这样遍历有什么问题?

    //假设值都为1,这里只赋值3个
    var arr = [204800]int{1, 1, 1} 
    for i, n := range arr {
        _ = i 
        _ = n 
    }
    第一种:对数组取地址遍历 for i, n := range &arr,因为数组去的是地址,而不是整个数组,所以在拷贝的时候是拷贝的地址,比整个数组要小得多。
    第二种:对数组做切片引用 for i, n := range arr[:]
     
    在for range中这样起goroutine能得到想要的结果么
    var m = []int{1, 2, 3}
    for i := range m {
        go func() {
            fmt.Print(i)
        }()
    }
    //阻塞1分钟等待所有goroutine运行完
    time.Sleep(time.Millisecond)
    因为很有可能当for循环执行完之后,goroutine才开始执行,这个时候val的值是指向了切片中最后一个元素。所以三个goroutine打印出来的结果相同
    for i := range m {
        go func(i int) {
            fmt.Print(i)
        }(i)
    }
     
     
     

     

     

     

     

posted @ 2023-03-08 08:48  刷刷题啊呀呀  阅读(15)  评论(0编辑  收藏  举报