01.Go语言基础语法

01.Go语言基础语法易错点总结

一.基础语法易错知识点

(一).数据类型

1.Golang是强类型语言。
2.在赋值过程中、类型必须保持一致。
3.变量必须先定义后使用,且必须用到。
4.golang会为每个变量设置默认值。
5.变量不能重名。
6.golang会根据类型做变量类型推断。
7.代码规范
    - 变量一般都是有小驼峰命名法
    - 如果外部引用 用大驼峰命名法
    - 数据库使用大驼峰命名法
8.数据库ORM参考学习
    https://github.com/go-gorm/gen

9.字符串和整型互转案例
	numType := 100
	fmt.Printf("Type: %T\n",strconv.Itoa(numType))
	str := "1000"
	ret,_ := strconv.Atoi(str)
	fmt.Printf("Type:%T\n",ret)

10.如下测试改变的是盒子里面放的内容,而不是盒子。
	age := "23"
	fmt.Printf("getMemoryAddress: %p\n",&age)

	age = "24"
	fmt.Printf("getMemoryAddress: %p\n",&age)

11.变量不可以重名 但是在新的作用域内是可以同名
	{
		var age string
		age = "jesseAge"
		fmt.Printf("我是新的作用域:%v\n",age)
	}
12.常量在整个生命周期都不允许修改。
    - 常量是在编译过程中计算好的值。
    - 变量是在运行过程中配置的值。
    - 常量只能支持: bool/string/数字。
    - 变量没有限制。

13.goland中 alt + shift+鼠标滑动 可以复制列。
    - alt+鼠标左键 单击选中多个光标进行修改。


14.运算符中a/b 如果都是int类型 结果将会舍去小数位直接显示整数位 需要也别注意。

15.位运算案例
    func bitCalc(){
        arr := []int{4,-3,4,5,6,-3,5,6,7}
        ret := -1
        for _,v := range arr{
            if ret <0 {
                ret = v
                fmt.Printf("ret<0: %v\n",ret)
            }else {
                ret = ret ^ v
                fmt.Printf("ret>=0: %v\n",ret)
            }
        }
        fmt.Printf("最终ret变量结果: %v\n",ret)
    }

16.fmt有迷惑性参数汇总
    %p    # 表示为十六进制,并加上前导的0x  
    %f    # 默认宽度,默认精度
    %9f   # 宽度9,默认精度
    %.2f  # 默认宽度,精度2
    %9.2f # 宽度9,精度2
    %9.f  # 宽度9,精度0 

17.课程涉及站点
    http://doc.golang.ltd/
    https://github.com/boltdb/bolt/
    https://crontab.guru/
    https://golangdocs.com/
    https://blog.gopheracademy.com/
    https://www.manning.com/books/the-programmers-brain
    https://forge.medium.com/the-easiest-thing-you-can-do-to-make-a-boring-job-better-7166d9e9e202

18.指定平台编译方式
    GOOS=windows GOARCH=amd64 go build -o bfr_x64.exe ./main.go //64bit Win
    GOOS=windows GOARCH=386 go build -o bfr_x32.exe ./main.go   //32bit Win
    GOOS=linux GOARCH=amd64 go build -o bfr_x64_linux ./main.go //64bit Linux

19.go mod初始化方式
    go mod init gocamp_home_study
    
20.pprof 性能分析相关
    https://golang.google.cn/pkg/runtime/pprof/
    https://golang.google.cn/pkg/net/http/pprof/#Index
    https://github.com/google/pprof/
    https://studygolang.com/articles/12970

21.keymap可以设置快捷键
22.General->Appearance->show whitespace 显示隐藏的字段。
23.NaN: not a number的简写。
24.windows->editor Tabs->split right/down // 分屏

25.双引号 单引号 反引号
    - 单引号表示byte类型或rune类型,对应uint8和int32类型,默认是rune类型。byte用来强调数据是raw data,而不是数字,而rune用来表示Unicode的code point。

    - 双引号才是字符串,实际上是字符数组。可以用索引号访问某字节,也可以用len()函数来获取字符串所占的字节长度。

    - 反引号,表示字符串字面量,但不支持任何转义序列。字面量raw literal string的意思是,你定义时写的啥样,它就啥样,你有换行,它就换行。你写转义字符,它也就展示转义字符。

    //示例
    func quoteTest(){
        //双引号"",可转义。
        x := "x\nquote\ttest"
        fmt.Printf("x is:%v,type is %T\n",x,x)

        //反引号``,保持原有格式输出
        var codeExample string =`
        func main(){
            fmt.Println("Hi Jesse~")
        }
        `
        fmt.Println(codeExample)

        //单引号'',通常用来表示rune类型,展示unicode。
        var a byte = 'H'
        fmt.Printf("a:%v,type:%T\n",a,a)

        b := '你'
        fmt.Printf("b:%v,type:%T\n",b,b)
    }

    //结果
    a:72,type:uint8
    b:20320,type:int32

26.字符串是utf-8编码,一个汉字三个字节,一个字母一个字节。
    //utf-8它可以使用1-4个字节表示一个字符,根据字符的不同变换长度。
    //字符长度和字节长度理解
    https://mp.weixin.qq.com/s/pXO4LxehqENEvRvxCXhG4A

27.Goland todo关键字
    //fixme 待修复bug
    //todo 待做事项

28.generate->Implement Methods
    - 自动创建未实现的方法。
    
29.选中字段名->refactor->rename // 批量修改

30.alt+shift+command+F 代码快速格式化
31.Mac下常用键盘符对应关系
    ⌘(command)
    ⌥(option)
    ⇧(shift)
    ⇪(caps lock)
    ⌃(control)
    ↩(return)
    ⌅(enter)
    如果不记得了 可以选择Mac下右上角的输入法图标,选择虚拟键盘即可看到对应关系。

(二).位操作符

1.与操作:&
    1 & 1 = 1 
    1 & 0 = 0 
    0 & 1 = 0 
    0 & 0 = 0

    #(The result of 5&6 is ', 4) 
    5 二进制为 101
    6 二进制为 110
    按照&的计算规则 相同为1 相异为0 5&6的结果二进制100 二进制100对应上面的4。

2.或操作:|
    1 | 1 = 1 
    1 | 0 = 1 
    0 | 1 = 1 
    0 | 0 = 0

    ('The result of 5|6 is ', 7)
    5 二进制为 101
    6 二进制为 110
    按照|的计算规则 只要有一个为1 结果就为1,5|6的结果二进制111 二进制111对应上面的7。

3.异或:^ 同0异1
    1 ^ 1 = 0 
    1 ^ 0 = 1 
    0 ^ 1 = 1 
    0 ^ 0 = 0

    ('The result of 5^6 is ', 3)
    5 二进制为 101
    6 二进制为 110
    按照|的计算规则 上下对应相异 结果就为1 5^6的结果二进制011 二进制011对应上面的3  正常情况会忽略前面的0。

4.左移:<<
    1 << 2 = 4
    ('The result of 1<<2 is ', 4) #1左移2位
    0000 0001 #1的二进制如左边 所有位数左移2位
    0000 0100 #左移2位结果如左边 对应十进制的4

5.右移:>>
    8 >> 2 = 2

    ('The result of 8>>2 is ', 2) #8右移2位案例
    0000 1000 #8的二进制。
    0000 0010 #所有右移2位结果 对应十进制2的二进制。

(二).源码/反码/补码

(三).array

1.自动计算数组的长度,不用再刻意定义。
    arr := [...]int{1,2,3,4,5}
	fmt.Println(arr)

2.数组赋值
    //如果没有赋值 默认结果为 a = [3]int{0,0,0}
    a := [3]int{}
    a[0]=1
    a[1]=2
    a[2]=3

3.数组和多维数组核心知识点测试代码
    //测试定长数组
    func arrayExample1(x [5]int){
        //原始值
        fmt.Println(x)

        //for循环打印结果方式
        for i:=0;i<len(x);i++{
            fmt.Printf("for: x[%d]=%d\n",i,x[i])
        }

        //for range 遍历数组打印结果方式
        for k,v := range x{
            fmt.Printf("range: x[%d]=%d\n",k,v)
        }
    }

    //测试变长 切片实现
    func arrayExample2(array2 []int){

        for i:=0;i<len(array2);i++{
            array2[i] = i+99
        }
        fmt.Println(array2)

        //测试数组长度自动计算获取
        array3 := [...]int{1,1,1,1,1}
        fmt.Println(array3)
    }


    //测试多维数组
    func arrarExample3(){
        var arr3 [3][3]int
        arr3 = [3][3]int{{1,2,4},{2,4,6},{23,23,23}}
        fmt.Println(arr3)

        //数组设置为变长
        var arr4 = [...][3]string{
            [3]string{"Jesse","23","engineer1"},
            [3]string{"Jesse1","24","engineer2"},
            [3]string{"Jesse2","25","engineer3"},
            [3]string{"Jesse3","26","engineer4"},
            [3]string{"Jesse4","27","engineer5"},
            [3]string{"Jesse5","28","engineer6"},
            [3]string{"Jesse6","29","engineer7"},
        }

        for _,v := range arr4{
            fmt.Println(v)
        }

        //多重遍历取最终值
        for x,y :=range arr4{
            for x1,y2 := range y{
                fmt.Printf("arr4[%d][%d]=%v\n",x,x1,y2)
            }

        }
    }

(四).slice

1.slice中一些比较关键的操作
    - 第一种
        make([]Type ,length, capacity)
        slice := make([]int, 3, 5) 

    - 第二种
        make([]Type, length)
        slice := make([]int, 5)

    - 第三种
        []Type{}
        slice := []int{}
    - 第四种
        slice := []int{1, 2, 3, 4, 5} //len是根据初始化长度而定的

    - 第五种
    //append内部实现了slice的自增,内部进行了make初始化。
    //append无论如何都是从slice的尾部开始追加数据,每次append 都要重新分配一次内存。
    func sliceStudy() {
        //追加元素
        a := []int{11, 22, 33}
        b := []int{1, 2, 3, 4, 4, 5}
        //如果append的数据为切片 别忘记...
        a = append(a, b...)
        fmt.Println("将b切片追加到a切片中。")
        fmt.Println(a)

        //删除元素4 ...表示追加多个元素
        c := []int{1, 2, 3, 4, 5, 6, 7, 8}
        c = append(c[:3], c[4:]...)
        fmt.Println(c)

        //删除多个元素 3 7 8
        d := []int{1, 2, 3, 4, 5, 6, 7, 8}
        d = append(d[:3], d[4:6]...)
        fmt.Println(d)
    }

    //copy以最小的为基准
    func copySlice(){
        x := make([]int,4) //dst
        y := []int{1,2,3} //src
        copy(x,y)
        fmt.Println(x)
    }

(五).map

1.map注意事项
    - 不用实例化就可以读取 删除。
    - 必须实例化才可以写入。
    - 重复删除相同的key,不会引起异常。

2.map初始化和案例
    - 第一种初始化方式
        var numbers map[string]int
        numbers = make(map[string]int)

    - 第二种声明并初始化
        number := make(map[string]int)

    - 案例
    func mapExample1() {
        m4 := map[string]int{"name": 1, "sex": 2, "addr": 3}
        m4["name"] = 111
        fmt.Println("m4:modify", m4)

        delete(m4, "sex")
        fmt.Println("m4:delete", m4)

        _, ok := m4["addr"]
        if ok {
            fmt.Println(m4["addr"])
        }

        //遍历map
        for k,v := range m4{
            fmt.Printf("k=%v,v=%v\n",k,v)
        }

    }
posted @ 2022-10-10 22:16  study-notes  阅读(86)  评论(0编辑  收藏  举报