基本结构和基本数据类型

文件名

文件名 正误
app.go 正确
start-app.go 错误
start_app.go 错误

标识符

Go 的标识符与 C 的要求类似,比如不能数字开头、不能使用关键字等。但 Go 可以使用任何 utf-8 字符来命名标识符,因此甚至可以使用中文。

关键字

  • 基本结构
    • 变量与常量
      • var
      • const
    • 包管理
      • package
      • import
  • 基本组件
    • 函数
      • func
      • return
    • 自定义类型
      • interface
      • struct
      • type
    • 引用类型
      • map
      • range
  • 流程控制
    • 并发
      • go
      • chan
      • select
    • 单任务流程控制
      • 单分支控制
        • if
        • else
      • 多分支流程
        • switch
        • case
        • default
        • fallthough
      • 循环流程
        • for
        • break
        • continue
      • goto
    • 延时型流程控制
      • defer

函数

main() 函数是每个可执行程序的入口,一般来说是第一个执行的入口函数(如果有 init() 函数会考虑先执行)。

函数的简单格式

1
2
3
func functionName() {

}

一般而言,函数如果需要被外部调用才会命名为首字母大写。

类型

Go 中可以被定义的类型包括:

  • 基本类型
    int float bool string

  • 结构化类型
    struct array slice map channel

  • 只描述类型的行为
    interface

1
* 结构化类型会使用 nil 作为默认值

Go 程序的一般结构

1. import 包之后开始对常量、变量和类型的定义
2. 如果存在 init 函数,则对函数开始定义
3. 如果当前包是 main 包,则定义 main 函数
4. 然后定义其余的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"fmt"
)

const c = "C"
var v int = 5

type T struct {

}

func init() {

}

func main() {
var a int

Func()
fmt.Println(a)
}

func (t T) Method1() {

}

func Func1() {

}

常量

存储在常量中的数据类型只能是布尔、数字和字符串类型。一般不能使用自定义函数,因为自定义函数的返回值在编译的过程中无法确定数值,因此无法用于常量的赋值,但是可以使用内置函数如 len()。

1
2
3
4
5
6
const (
Sunday = itoa
Monday
// ...
Saturday
)

变量

当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil。记住,所有的内存在 Go 中都是经过初始化的。

基本运算符

使用左移实现存储单位的常量定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type ByteSize float64
const (
_ = itoa // 通过赋值给空白标识符来忽略值

KB ByteSize = 1<<(10*itoa)
MB
GB
TB
PB
EB
ZB
YB
)

Go 中的一元运算符 (++ 或 –) 只能用于后缀,而不能像 C++ 那样可以放在前面,同时一元运算符只能作为语句而不能当做表达式,即 f(a++) 或者 n=i++ 这些能在 C++ 中实现的写法在 Go 中不被允许。

字符类型

严格来说,Go 中的字符类型是整数的特殊用例(在语言层面表现为 byte 类型其实是 uint8 的别名),对于单字节字符来说,使用 ASCII 码即可解决问题。如以下代码是等效的。

1
2
3
4
5
var ch byte = 65
var ch byte = '\x41'
var ch byte = '\377'

// 以上三种写法均是字符 A 的写法,分别对应十进制、十六进制和八进制

strings 包

  • 前缀和后缀
1
2
strings.HasPrefix(s, prefix string) bool    // 前缀判断
strings.HasSuffix(s, suffix string) bool // 后缀判断
  • 字符串包含关系
1
2
3
4
5
strings.Contain(s, substr string) bool      // 子串包含
strings.Index(s, str string) int // 子串索引 KMP 算法?
strings.LastIndex(s, str string) int // 最后一个子串索引
strings.IndexRune(s, ch int) int // 非 ASCII 字符的索引推荐
strings.Count(s, str string) int // 计算 str 在 s 中非重叠出现的次数
  • 字符串的替换
1
2
// 将字符串 str 中的前 n 长度的子串的所有 old 子串替换为 new 子串,-1 代表全局替换
strings.Repalce(str string, old string, new string, n int)
  • 重复字符串
1
strings.Repeat(s, count int) string
  • 大小写修改
1
2
strings.ToLower(s) string
strings.ToUpper(s) string
  • 字符串修剪
1
2
3
4
strings.TrimSpace(s)                // 剔除开头结尾的空白字符
strings.Trim(s, cut string) // 剔除指定字符
strings.TrimLeft(s, cut string) // 剔除指定字符
strings.TrimRight(s, cut string) // 剔除指定字符
  • 字符串分割
1
2
strings.Field(s)                    // 通过空白符分割
strings.Split(s, sep string) // 通过指定分割符号分割
  • 字符串拼接
1
strings.Join(s1 []string, sep string)// 类比 Python 中的 join

strconv 包

主要方便为 string 类型转换为其他类型提供方法。一般会将 string 转换为 float 或者 int 等。

time 包

time 包提供了一个数据类型(time.Time)用于表示时间并实现时间的功能函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

package main
import (
"fmt"
"time"
)

// Duration 为毫秒的数据结构,一般作为时间处理的计算单位。
var (
week time.Duration
)

func main() {
t := time.Now()
fmt.Println(t) // e.g. Wed Dec 21 09:52:14 +0100 RST 2011
fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year())
// 21.12.2011
t = time.Now().UTC()
fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011
fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011
// calculating times:
week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec
week_from_now := t.Add(week)
fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011
// formatting times:
fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC
fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011
fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52
s := t.Format("20060102")
fmt.Println(t, "=>", s)
// Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221
}

指针

Go 语言提供了控制数据结构的指针的能力,但是 Go 为了安全考虑的指针不能进行偏移运算。使用指针对于后端开发来说可以大幅提升程序的性能。