Go语言中文文档-1Go基础

Go于2009年由谷歌推出。

Init函数和main函数

Init函数

用于程序执行前初始化包变量
每个包可以多个,同一个包多个init执行顺序无明确定义
按照包导入依赖关系决定不同包初始化函数执行顺序
不能被调用,main函数执行前自动被调用

与main函数异同

相同点:
都不能有参数和返回值,都是go程序自动调用。
不同点:
init可以用于不同包,可定义多个。
main只能用于main包,只能定义一个。

命令

go env打印Go语言环境
go run编译运行命令源码文件
go get从互联网下载代码包依赖包编译和安装
go build编译源码文件、代码包及依赖包
go install编译并安装代码包及依赖包
go doc + Go实体 查看文档
go test测试go编写的程序
go list列出代码包信息

运算符

自增自减不是运算符

下划线

下划线在import中

import _ "./hello"
表示程序引用包中所有init函数,并不能通过包名调用包中其他函数。

下划线在代码中

表示忽略这个变量,如果用变量不使用,编译器报错。

变量和常量

变量

变量声明后必须使用
标准声明:var name string
批量声明:var (
a string
b int
c bool
d float32
)
类型推导: var sex = 1
函数内部短变量声明:n := 100
匿名变量:x, _ = foo()不占命名空间,不分配内存

常量

const pi = 3.1415

const (
a = 1
b
)
上述b == a

iota
常量计数器,只能在常量表达式使用。

基本类型

整型

int64对应C语言long

多行字符串

定义时必须使用反引号字符

字符串常用操作

分割:strings.Split
判断是否包含:strings.Contains
前后缀判断:strings.HasPrefix, strings.HasSuffix
子串位置:strings.Index(), strings.LastIndex()
join操作:strings.Join(a[]string, sep string)

byte rune

byte: ASCII类型
rune:UTF-8

修改字符串

先转换成[]rune, []byte完成后再转换为string

类型转换

go只有强制类型转换,无隐式类型转换

数组Array

var a[5] int和var a [10]int是不同类型
指针数组 [n]* T, 数组指针 *[]T
数组初始化:var arr = [...]int{1, 2, 3, 4, 5, 6}
var arr1 = [5]int{2: 100, 4: 200}
var arr2 = [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
len, cap都返回数组长度。

切片Slice

切片是引用类型,自身是结构体,值拷贝传递。
创建切片:var s1 []int
s2 := []int{1, 2, 3}
var s3 []int = make([]int, len, cap)省略cap则cap = len
s1 := []int{0, 1, 2, 3, 8:100}
data := [][]int{
[]int{1, 2, 3},
[]int{100, 200},
[]int{11, 22, 33, 44},
}
d := [5]struct {
x int
}{}
c = append(s1, s2...)
超出slice.cap限制,就会重新分配底层数组。通常两倍容量重新分配。
数组或切片转字符串: strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",", -1)

slice底层实现

切片数据结构

切片通过指针引用底层数组,切片是只读对象,是对类似数组指针的封装。

空切片和nil切片

空切片:var slice []int一般表示一个空集合
nil切片:slice := make([]int, 0)函数发生异常时返回
slice := []int{}
上述区别,一个指针指向内存地址,一个指针为nil

扩容策略

如果切片容量小于1024,两被扩容到新地址,不改变原数组
如果切片容量超过1024,1.25倍扩容
扩容针对原来容量,不针对原数组长度。

指针

Go指针不能偏移与运算

new和make

Go语言对引用类型变量,使用时要为之分配内存,对值类型,使用时默认分配好了内存空间。

new

a := new(int)
指针作为引用类型,声明后必须用new初始化后才可以为指针指向的值赋值。

make

使用slice、map、channel时,都需要使用make进行初始化。

new、make区别

make返回引用类型本身, new返回指向类型的指针。
make用于slice、map、channel初始化,而new用于类型内存分配

Map

map是无序的kv数据结构,是引用类型,初始化后可以使用。
定义: map[KeyType]ValueType
分配内存:make(map[KeyType]ValueType, [cap])
判断某个键是否存在:value, ok := map[key]
if ok {
} else {
}
遍历:for k, v := range m {
}
for k := range m {
}
遍历顺序不一定是添加顺序
删除键值对:delete(m, key)

Go中Map的实现原理

通过桶的方式解决冲突问题,key,value分开存储以节省内存空间,每个桶存放元素有最大数量,超过最大数量则通过overflow获取链表上的下一个桶。

结构体

自定义类型:
type MyInt int
类型别名:
type byte = uint8
自定义类型和类型别名的区别
自定义类型后通过新类型定义变量,输出变量类型为新类型。
类型别名后,仍然输出原类型。
匿名结构体:
var user struct{Name string; Age int}
创建指针类型结构体:
var p2 = new(person)
取结构体的地址实例化
p3 := &person{}
使用值的列表初始化:
p8 := &person {
1,
"aa",
}
上述方式必须初始化所有字段,必须与声明方式一致,不能和键值初始化混用。

构造函数

func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}
p9 := newPerson("pprof.cn", "测试", 90)

方法和接收者

方法:作用于特定类型变量的函数
方法属于特定的类型,函数不属于任何类型。
什么时候应该使用指针类型接收者?
需修改接受者值,接受者拷贝代价高,方法使用的接受者一致性(如都是指针接受者)。

Go中任意类型都可以拥有方法,但我们不能给别的包的类型定义方法。

结构体字段的可见性

结构体中字段大写开头表示可公开访问,小写表示仅在当前结构体包中访问。

结构体与JSON序列化

序列化
data, err := json.Marshal(c)
反序列化
err = json.Unmarshal([]byte(str), c1)

结构化标签

Tag: 结构体的元信息
key1:"value1" key2:"value2"

实现map有序输出

点击查看代码
package main

import (
    "fmt"
    "sort"
)

func main() {
    map1 := make(map[int]string, 5)
    map1[1] = "www.topgoer.com"
    map1[2] = "rpc.topgoer.com"
    map1[5] = "ceshi"
    map1[3] = "xiaohong"
    map1[4] = "xiaohuang"
    sli := []int{}
    for k, _ := range map1 {
        sli = append(sli, k)
    }
    sort.Ints(sli)
    for i := 0; i < len(map1); i++ {
        fmt.Println(map1[sli[i]])
    }
}

posted @   人生hh  阅读(1238)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示