go语言基础 | 青训营笔记

126 阅读5分钟

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

  1. 背景

  1. 特征

Go 语言最主要的特性:

  • 自动垃圾回收

  • 更丰富的内置类型

  • 函数多返回值

  • 错误处理

  • 匿名函数和闭包

  • 类型和接口

  • 并发编程

  • 反射

  • 语言交互性

  1. 基础知识

  1. 结构

 /* 包声明 */
package main 

/* 引入包 */
import "fmt"

/* 函数 */
func main() { // { 不能在单独的行上
   /* 这是我的第一个简单的程序 */
   fmt.Println("Hello, World!")
}
  1. 执行

第一种:直接运行

go run hello.go

第二种:使用 go build 命令来生成二进制文件

go build hello.go
./hello
  1. 格式化字符串(fmt)

Go 语言中使用 fmt.Sprintffmt.Printf 格式化字符串并赋值给新串:

  • Sprintf 根据格式化参数生成格式化的字符串并返回该字符串。

  • Printf 根据格式化参数生成格式化的字符串并写入标准输出。

  1. 数据类型

类型描述
布尔型布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。
数字类型整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
字符串类型字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型包括:(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型
  1. 变量

声明变量的一般形式是使用 var 关键字:

var identifier type

// 这种因式分解关键字的写法一般用于声明全局变量
var (
    vname1 v_type1
    vname2 v_type2
)

可以一次声明多个变量:

var identifier1, identifier2 type

如果没有初始化,则变量默认为零值(变量没有做初始化时系统默认设置的值)

  1. 常量

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

const identifier [type] = value

可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型

  1. 条件语句

  • If
if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
}

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

if 布尔表达式 1 {
   /* 在布尔表达式 1 为 true 时执行 */
   if 布尔表达式 2 {
      /* 在布尔表达式 2 为 true 时执行 */
   }
}
  • switch

    • 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough
switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}
  1. 循环语句

for init; condition; post { }
init: 一般为赋值表达式,给控制变量赋初值;
condition: 关系表达式或逻辑表达式,循环控制条件;
post: 一般为赋值表达式,给控制变量增量或减量。

for condition { }

for { }
  1. 数组

  • 声明
var variable_name [SIZE] variable_type
  • 初始化
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

长度不确定
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
  • 访问

    • 可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值
var salary float32 = balance[9]
  1. 切片(Slice)

var identifier []type

var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)
  1. 集合(Map)

/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key

delete(map, key)
  1. 范围(Range)

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素

在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对

for key, value := range oldMap {
    newMap[key] = value
}
  1. 函数

func function_name( [parameter list] ) [return_types] {
   函数体
}
  1. 指针

一个指针变量指向了一个值的内存地址

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容

当一个指针被定义后没有分配到任何变量时,它的值为 nil

func main() {
   var a int= 20   /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址是: %x\n", &a  )

   /* 指针变量的存储地址 */
   fmt.Printf("ip 变量储存的指针地址: %x\n", ip )

   /* 使用指针访问值 */
   fmt.Printf("*ip 变量的值: %d\n", *ip )
}
  1. 结构体(struct)

type struct_variable_type struct {
   member definition
   member definition
   ...
   member definition
}

访问

结构体.成员名
  1. 错误处理

error类型是一个接口类型,可以在编码中通过实现 error 接口类型来生成错误信息

定义
type error interface {
    Error() string
}

使用errors.New 可返回一个错误信息

errors.New("math: square root of negative number")
  1. String

func main() {
    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
    b := "你好"
    fmt.Println(len(b)) // 6
}
  1. JSON

引入包

import (
    "encoding/json"
    "fmt"
)

定义:变量名首字母要大写

type userInfo struct {
    Name  string
    Age   int `json:"age"`
    Hobby []string
}

使用

a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)
if err != nil {
    panic(err)
}
fmt.Println(buf)         // [123 34 78 97...]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}