初探 Go| 青训营笔记

65 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第1天。

本文重点内容

  • Go 准备与环境配置
  • Go基础语法

重点知识点介绍

背景知识

Go是一门编译型语言,Go语言的工具链将源代码及其依赖转换成计算机的机器指令(译注:静态编译)。Go语言提供的工具都通过一个单独的命令go调用,go命令有一系列子命令。最简单的一个子命令就是run。这个命令编译一个或多个以.go结尾的源文件,链接库文件,并运行最终生成的可执行文件。(本书使用$表示命令行提示符。)

Go模块代理

七牛云 - Goproxy.cn

命名

Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的:heapSort和Heapsort是两个不同的名字。

Go语言中类似if和switch的关键字有25个;关键字不能用于自定义名字,只能在特定语法结构中使用。

 break      default       func     interface   select
 case       defer         go       map         struct
 chan       else          goto     package     switch
 const      fallthrough   if       range       type
 continue   for           import   return      var

此外,还有大约30多个预定义的名字,比如int和true等,主要对应内建的常量、类型和函数。

 内建常量: true false iota nil
 ​
 内建类型: int int8 int16 int32 int64
           uint uint8 uint16 uint32 uint64 uintptr
           float32 float64 complex128 complex64
           bool byte rune string error
 ​
 内建函数: make len cap new append copy close delete
           complex real imag
           panic recover

这些内部预先定义的名字并不是关键字,你可以在定义中重新使用它们。在一些特殊的场景中重新定义它们也是有意义的,但是也要注意避免过度而引起语义混乱。

如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问。名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的(译注:必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问。包本身的名字一般总是用小写字母。

名字的长度没有逻辑限制,但是Go语言的风格是尽量使用短小的名字,对于局部变量尤其是这样;你会经常看到i之类的短名字,而不是冗长的theLoopIndex命名。通常来说,如果一个名字的作用域比较大,生命周期也比较长,那么用长的名字将会更有意义。

在习惯上,Go语言程序员推荐使用 驼峰式 命名,当名字由几个单词组成时优先使用大小写分隔,而不是优先用下划线分隔。因此,在标准库有QuoteRuneToASCII和parseRequestLine这样的函数命名,但是一般不会用quote_rune_to_ASCII和parse_request_line这样的命名。而像ASCII和HTML这样的缩略词则避免使用大小写混合的写法,它们可能被称为htmlEscape、HTMLEscape或escapeHTML,但不会是escapeHtml。

数据与容器

  1. Go中变量可以定义类型(在变量名称后声明)或者不定义。

    两种方式的例子:var b, c int = 1, 2

  2. 常量用const声明

  3. 字符串可以直接+相连:g := a + "foo"

  4. switch语句可以用来代替传统if-else

     switch {
         case t.Hour() < 12:
            fmt.Println("It's before noon")
         default:
            fmt.Println("It's after noon")
     }
    
  5. 数组的两种定义方式

    var a [5]int

    b := [5]int{1, 2, 3, 4, 5}

  6. 切片的两种定义方式

    c := make([]string, len(s))

    good := []string{"g", "o", "o", "d"}

  7. map的两种定义方式

    m := make(map[string]int)

    m2 := map[string]int{"one": 1, "two": 2}

  8. rangemap键值对的用法

     m := map[string]string{"a": "A", "b": "B"}
     for k, v := range m {
        fmt.Println(k, v) // b B; a A
     }
     for k := range m {
        fmt.Println("key", k) // key a; key b
     }
    

传参类型

Go中默认为传值,经过设置后可以传址(引用),处理数据用&,声明类型和指代变量用*

image.png

结构体

结构体赋值类似于Json,结构体中可以带成员函数,用前导括号表示,带指针版能修改内部内容。

 type user struct {
    name     string
    password string
 }
 ​
 func checkPassword(u user, password string) bool {
    return u.password == password
 }
 //结构体成员函数
 func (u user) checkPassword(password string) bool {
    return u.password == password
 }
 //带指针版能修改内部内容
 func (u *user) resetPassword(password string) {
    u.password = password
 }
 ​
 func main(){
     c := user{name: "wang"}
 }

strings常用函数

字符串相关处理的函数,总结如下:

 a := "hello"
 fmt.Println(strings.Contains(a, "ll"))                // true
 fmt.Println(strings.Count(a, "l"))                    // 2
 fmt.Println(strings.HasPrefix(a, "he"))               // true
 fmt.Println(strings.HasSuffix(a, "llo"))              // true
 fmt.Println(strings.Index(a, "ll"))                   // 2
 fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
 fmt.Println(strings.Repeat(a, 2))                     // hellohello
 fmt.Println(strings.Replace(a, "e", "E", -1))         // hEllo
 fmt.Println(strings.Split("a-b-c", "-"))              // [a b c]
 fmt.Println(strings.ToLower(a))                       // hello
 fmt.Println(strings.ToUpper(a))                       // HELLO
 fmt.Println(len(a))                                   // 5
 ​
 strings.Trim(input, "\r\n")
 strings.NewReader(`{"trans_type":"en2zh","source":"he"}`)

本文小结

多种数据类型与结构体、容器、以及字符串的相关介绍

参考资料与引用

学习资源