Golang 基础总结

一、简介

  • Go(又称Golang)是Google开发的一种静态、强类型、编译型、并发型,并具有垃圾回收功能的编程语言

二、变量 & 常量

2.1 变量

  • 声明var name type
  • 变量声明后,会自动初始化

int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil

  • 命名规则遵循骆驼命名法
    var a, b int
    var p *int
    var f int = 99

    //批量
    var (
        c int
        d string
    )

    //简写
    s := "string"
    x, y := 1.0, 2.0

    //值交换
    x, y = y, x

    fmt.Println(a, b, f, c, d, p, s, x, y) //0 0 99 0   string 2 1

  • 匿名变量
func getPoint() (int, int) {
    return 100, 200
}
    xPoint, _ := getPoint()
    _, yPoint := getPoint()
    fmt.Println(xPoint, yPoint)

2.2 常量

  • const关键字
  • 只能是布尔型、数字型(整数型、浮点型和复数)和字符串型
  • 定义常量的表达式必须为能被编译器求值的常量表达式
  • 声明,类型可选
    const name [type] = value
  • iota

三、基本数据类型

3.1 布尔型

  • 关键字bool
  • 值仅有true or false
  • 默认值false
  • 存在短路行为,既如果运算符左边的值可以确定整个布尔表达式的结果,则运算符右边不再执行(同其他语言)

3.2 字符串

  • 关键字string
  • 默认值为空
  • 值为任意数据的不可变字节序列
  • UTF-8 字符占位(ASCII上的字符占一个字节,其他占两个字节)
  • 转义字符
    \n换行符
    \r回车符
    \ttab 键
    \u 或 \UUnicode 字符
    \\反斜杠自身
  • 比较运算符(==、!=、<、<=、>=、>)
  • 获取大小len()
  • 字符串操作,借助于strings
str1 := "!"
//拼接
str := "Hello world" + str1
//索引
fmt.Println(str[0]) //72
//截取(取前不取后)
fmt.Println(str[0:4]) //hell
//是否包含
fmt.Println(strings.Contains(str, "hello")) //true
fmt.Println(strings.Contains(str, "h & k")) //false
//是否包含多个
fmt.Println(strings.ContainsAny(str, "h & k")) //true
//是否以子串开始
fmt.Println(strings.HasPrefix(str, "hello")) //true
//是否以子串结束
fmt.Println(strings.HasSuffix(str, "!")) //true
//大小写
fmt.Println(strings.ToLower(str)) //hello world!
fmt.Println(strings.ToUpper(str)) //HELLO WORLD!
//获取索引,查找不到返回-1
fmt.Println(strings.Index(str, "l")) //2
fmt.Println(strings.LastIndex(str, "l")) //9
//匹配多个字节组成的字符
fmt.Println(strings.IndexRune("城市花园", '花')) //6

//切片
fmt.Println(strings.Split(str, " ")) //[Hello world!]
//组合(元素类型为string)
fmt.Println(strings.Join(strings.Split(str, " "), " ")) //Hello world!
fmt.Println(strings.Join([]string{"a", "b", "c"}, ", ")) //a, b, c


//替换(参数:源字符串,需要替换, 新字符串, 匹配前n个记录)
fmt.Println(strings.Replace(str, "world", "Jony", 1)) //Hello Jony!

  • 多行时必须使用反引号`,既字符串字面量
var s string = `First line
    hello
    end line
    `
  • 类型转换,strconv
num, _ := strconv.Atoi("10")
fmt.Println(num-1) //9

3.3 数值类型

整数
  • 有符号
    int、int8、int16、int32、int64
  • 无符号
    uint、uint8、uint16、uint32、uint64、uintptr

注:int和uint会因编译器和计算机硬件,大小会在 32bit 或 64bit 之间变化

浮点数
  • float32 EEE-754 32位浮点型数
  • float64 IEEE-754 64位浮点型数
复数
  • complex64 32 位实数和虚数
  • complex128 64 位实数和虚数

四、派生类型

4.1 指针(pointer)

  • 声明
    var var_name *var-type
  • 取地址操作符&
  • 指针变量取指向地址保存数据操作符*
  • fmt.Printf打印内存地址%f
  • 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算
    data := "pointer data"
    ptr := &data
    fmt.Printf("%p\n", &data) //0xc00008a040
    fmt.Println(ptr) //0xc0000681e0
    fmt.Println(*ptr) //pointer data

    str := new(string)
    *str = "string data"
    fmt.Printf("%p\n", str) //0xc000098050
    fmt.Printf("%s\n", *str) //string data

    //空指针取值会报错
    var nullPointer *string
    if(nullPointer == nil) {
        fmt.Println(nullPointer) //
    }

4.2 数组

  • 声明
    var 数组变量名 [元素数量]Type
  • 定长特定类型的元素序列
    var intArr [3]int
    var arr1 [3]int = [3]int{1, 2} 
    arr2 := [...]int{1, 2, 0}
    arr3 := [2]int{1, 2}

    fmt.Println(intArr) //[0 0 0]
    fmt.Println(arr1) //[1 2 0]
    fmt.Println(arr2) //[1 2 0]
    fmt.Println(arr1 == arr2) //true
    // fmt.Println(arr1 == arr3) //error

    //数组遍历
    for k, v := range arr3 {
        fmt.Println(k, v)
    }

    //多维数组
    var multArr [2][3]int
    //此种方式初始化一行的元素可以省略自动使用默认值,但不能省略一行否则报错
    multArr = [2][3]int{{1, 2, 3}, {4, 5}} //[[1 2 3] [4 5 0]]
    fmt.Println(multArr)

    multArr1 := [4][3]int{1:{1, 1, 1}, 3:{3, 3, 3}}
    fmt.Println(multArr1) //[[0 0 0] [1 1 1] [0 0 0] [3 3 3]]
    fmt.Println(multArr1[3]) //[3 3 3]
    multArr1[2][1] = 99
    fmt.Println(multArr1) //[[0 0 0] [1 1 1] [0 99 0] [3 3 3]]

4.3 切片

  • 切片(slice)是对数组的一个连续片段(整个数组,由起始和终止索引标识的一些项的子集)的引用(对数组的抽象)
  • 切片结构包含地址、大小和容量
  • 大小不固定
  • 声明
    var name []Type
    //从数组中生成切片
    arr := [...]int{1, 2, 3, 4, 5}
    fmt.Println(arr) //[1 2 3 4 5]
    fmt.Println(arr[0:0]) //[]
    fmt.Println(arr[:]) //[1 2 3 4 5]
    fmt.Println(arr[2:]) //[3 4 5]
    fmt.Println(arr[:2]) //[1 2]
    fmt.Println(arr[1:3]) //[2 3]

    //声明切片
    var strSlice []string
    var intSlice []int
    var emptySlice = []int{} //分配到了内存,但无元素
    fmt.Printf("%p, %p, %p\n", strSlice, intSlice, emptySlice) //0x0, 0x0, 0x1195ab8
    fmt.Println(strSlice, intSlice, emptySlice) //[] [] []
    fmt.Println(strSlice == nil) //true
    fmt.Println(emptySlice == nil) //false

    //append()函数添加元素,返回一个切片
    fmt.Println(append(intSlice, 1)) //[1]
    fmt.Println(append(intSlice, 1, 2)) //[1 2]
    //追加的为切片时需解包
    fmt.Println(append(intSlice, []int{1, 2, 3}...)) //[1 2 3]

    //使用 make() 内建函数,动态地创建一个切片
    s1 := make([]int, 2)
    s2 := make([]int, 2, 6)
    fmt.Println(s1, s2) //[0 0] [0 0]

    //copy
    slice1 := []int{1, 1, 1}
    slice2 := []int{2, 2, 2, 2, 2}
    copySlice1 := make([]int, 5)
    copySlice2 := make([]int, 3)
    copy(copySlice1, slice1)
    copy(copySlice2, slice2)
    fmt.Println(copySlice1) //[1 1 1 0 0]
    fmt.Println(copySlice2) //[2 2 2]

4.4 Map

  • 声明
    var mapname map[keytype]valuetype
    make声明可选标明大小make(map[keytype]valuetype, cap)
  • 仅只读线程安全
    var emptyMap map[string]int
    emptyMap1 := make(map[string]int, 10)
    fmt.Println(emptyMap, emptyMap1) //map[] map[]

    mapList := map[string]int{"key1":1, "key2":2}
    fmt.Println(mapList, len(mapList)) //map[key1:1 key2:2] 2
    mapList["key3"] = 3
    for key, value := range mapList {
        fmt.Println(key, value)
    }

    //删除
    delete(mapList, "key2")
    fmt.Println(mapList) //map[key1:1 key3:3]

value 值
  • 实测为Map 或者切片时正确,为数组时报错
type Rcus struct {
    Id bson.ObjectId
    RoomNum string
    AirconMap map[string][]int
    DmMap map[string]int
}
    rcu := new(models.Rcus) //已经初始化各个成员
    // rcu := &(models.Rcus)
    rcu.Id = bson.NewObjectId()
    rcu.RoomNum = "1204"

    //正确
    // ariconMap := make(map[string][]int)
    // aircon1 := []int{1, 2, 3, 4}
    // ariconMap["AC1"] = aircon1
    // ariconMap["AC2"] = []int{1, 2, 3, 4} 
    // rcu.AirconMap = ariconMap


    //正确
    // aircon := []int{1, 2, 3, 4}
    // rcu.AirconMap = map[string][]int{"ac":aircon}

    rcu.DmMap = map[string]int{"1":1}

    fmt.Println(rcu)
sync.Map
  • 优于加锁解决map线程安全,sync 包下的特殊结构
  • 无须初始化,直接声明即可
    //sync package
    var syncMap sync.Map
    //存储
    syncMap.Store("key1", 1)
    syncMap.Store("key2", 2)
    syncMap.Store("key3", 3)
    //获取值
    fmt.Println(syncMap.Load("key2")) //2 true
    //删除
    syncMap.Delete("key3")
    //遍历
    syncMap.Range(func(k, v interface{}) bool {
        fmt.Println(k, v)
        return true //true 继续,false 结束
    })

其他:函数、Channel、接口、结构体

四、常用标准库

包名 功能
bufio 带缓冲的 I/O 操作
bytes 实现字节操作
container 封装堆、列表和环形列表等容器
crypto 加密算法
database 数据库驱动和接口
debug 各种调试文件格式访问及调试功能
encoding 常见算法如 JSON、XML、Base64 等
flag 命令行解析
fmt 格式化操作
go Go语言的词法、语法树、类型等。可通过这个包进行代码信息提取和修改
html HTML 转义及模板系统
image 常见图形格式的访问及生成
io 实现 I/O 原始访问接口及访问封装
math 数学库
net 网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等
os 操作系统平台不依赖平台操作封装
path 兼容各操作系统的路径操作实用函数
plugin Go 1.7 加入的插件系统。支持将代码编译为插件,按需加载
reflect 语言反射支持。可以动态获得代码中的类型信息,获取和修改变量的值
regexp 正则表达式封装
runtime 运行时接口
sort 排序接口
strings 字符串转换、解析及实用函数
time 时间接口
text 文本模板及 Token 词法器

你可能感兴趣的:(Golang 基础总结)