类型和结构体都可以定义方法,可被调用
一 :配置 GOPROXY加速
Linux
# 启用 Go Modules 功能
go env -w GO111MODULE=on
# 配置 GOPROXY 环境变量,以下三选一
# 1. 七牛 CDN
go env -w GOPROXY=https://goproxy.cn,direct
# 2. 阿里云
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
# 3. 官方
go env -w GOPROXY=https://goproxy.io,direct
# 确认一下:
$ go env | grep GOPROXY
GOPROXY="[https://goproxy.cn](https://goproxy.cn/)"
Win
# 启用 Go Modules 功能
$env:GO111MODULE="on"
# 配置 GOPROXY 环境变量,以下三选一
# 1. 七牛 CDN
$env:GOPROXY="https://goproxy.cn,direct"
# 2. 阿里云
$env:GOPROXY="https://mirrors.aliyun.com/goproxy/,direct"
# 3. 官方
$env:GOPROXY="https://goproxy.io,direct"
# 确认一下:
$ go env | findstr GOPROXY
GOPROXY="[https://goproxy.cn](https://goproxy.cn/)"
二: 常用包
可以给包别名从而实现避免命名冲突
import fm “fmt”
fmt : C 的 printf 和 scanf 的功能实现格式化的 I/O 包
rand : 伪随机数的生成
strings : 简单的函数来操作 UTF-8 编码的字符串。
time : 提供了测量和显示时间的功能
三 : 入门
导包制
import “”
变量声明 名前 类后
单个 := 局部变量
var variable DataTypes // 显式
name := "string" // 隐式短声明 !!!全局变量不可用
多个 其他定义的也可使用
// 不同之一
var (
s1 string = "1";
s2 string = "2";
)
常量 const
// 允许并行赋值
const beef, two, c = "eat", 2, "veg"
const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)
// 可使用枚举
const (
Unknown = 0
Female = 1
Male = 2
)
类型转换
value_Of_TypeB = typeB(value_Of_TypeA)
外部访问 首字母大写的变量 函数 可被外面的包访问
输入/输出
引入 fmt 包
fml.printf("%v 你好吖", wood) %v是任意匹配数据类型 特有其他基础和C差不多
%#v 可以将空的字符串打印出来 "" 原始的指
var f = fml.Sprintf("%v 你好吖", wood)
fmt.printf(f)
// 输入使用
var name string
fmt.Scan(&name)
数据类型与关键词
byte 单字节
rune 8字节
自定义数据类型
type Code int
type Number interface{
int|uint|int8|int16
}
const (
SuccessCode Code = 0
ValidCode Code = 7 // 校验失败的错误
ServiceErrCode Code = 8 // 服务错误
)
func (c Code) GetMsg() string {
// 可能会有更加响应码返回不同消息内容的要求,我们在这个函数里面去实现即可
// 可能还会有国际化操作
return "成功"
}
func main() {
fmt.Println(SuccessCode.GetMsg())
var i int
fmt.Println(int(SuccessCode) == i) // 必须要转成原始类型才能判断
}
自定义类型别名
type Code = int
- 不能绑定方法
- 打印类型还是原始类型
- 和原始类型比较,类型别名不用转换
关键词
_ | 空白识别符 : 任何赋给这个标识符的值都将被抛弃 |
---|---|
nil | 类似于Null 空值 |
const | 声明常量 |
var | 声明变量 |
type | 定义结构体? |
lota | 遇到一个变量会+1 遇到常量guilubg3 |
break | 跳出当前的执行 |
运算符 同C
位移存在 1 << 10 10 >> 1
数组
var arrlist [i]Datatype = [i]Datatype{}
var nameList []Datatype
nameList = append(nameList, "")
nameList = append(nameList, "")
var nameList []string = []string{}
nameList = make([]string, 0) ||
/* 不需要上面初始化 */
nameList := make([]string, 0)
make([]Datatype, length, capacity)
切片 slice 可变长度的固定type 数组
S := []int{1,2,3,4,5,6}
s1 := S[:3] // 从前三个取
s2 := S[3:] // 从后三个取
var nameList []string
nameList = append(nameList, "")
nameList = append(nameList, "")
指针
& 取值符号
- 解引用 将值指向原地址
func main() {
s := "good bye"
var p *string = &s
*p = "ciao"
fmt.Printf("Here is the pointer p: %p\n", p) // prints address
fmt.Printf("Here is the string *p: %s\n", *p) // prints string
fmt.Printf("Here is the string s: %s\n", s) // prints same string
}
func Expo
结构体指针
type Student struct {
Name string
Age int
}
func SetAge(info Student, age int) {
info.Age = age
}
func SetAge1(info *Student, age int) {
info.Age = age
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
fmt.Println(s.Age)
SetAge(s, 18)
fmt.Println(s.Age)
SetAge1(&s, 17)
fmt.Println(s.Age)
}
type Student struct {
Name string
Age int
}
func (s Student) SetAge(age int) {
s.Age = age
}
func (s *Student) SetAge1(age int) {
s.Age = age
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
s.SetAge(18)
fmt.Println(s.Age)
s.SetAge1(18)
fmt.Println(s.Age)
}
map 映射
// 初始化
var aMap = make(map[string]string)
var aMap = map[string]string{}
var usrMap map[int]string = map[int]string{
1: "wood",
2: "bird",
}
fmt.Println(usrMap)
fmt.Println(usrMap[1])
fmt.Println(usrMap[2])
fmt.Printf("%#v\n", usrMap[4])
valuse , static = userMap[4]
// valuse是 map[int]string 这里定义的string
// static 是bool 判断是否有值
delete(usermap, key值)
--------------------------------
map[1:wood 2:bird]
wood
bird
""
结构体
type People struct {
Time string
}
func (p People) Info() {
fmt.Println("people ", p.Time)
}
// Student 定义结构体
type Student struct {
People
Name string
Age int
}
// PrintInfo 给机构体绑定一个方法
func (s Student) PrintInfo() {
fmt.Printf("name:%s age:%d\n", s.Name, s.Age)
}
func main() {
p := People{
Time: "2023-11-15 14:51",
}
s := Student{
People: p,
Name: "枫枫",
Age: 21,
}
s.Name = "枫枫知道" // 修改值
s.PrintInfo()
s.Info() // 可以调用父结构体的方法
fmt.Println(s.People.Time) // 调用父结构体的属性
fmt.Println(s.Time) // 也可以这样
}
结构体标签
type Student struct {
Name string `json:"name"` // Name -> name
Age int `json:"age"`
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
byteData, _ := json.Marshal(s)
fmt.Println(string(byteData))
}
接口
type SingInterface interface {
Sing()
GetName() string
}
type Chicken struct {
Name string
}
func (c Chicken) Sing() {
fmt.Println(c.Name, "Sin")
}
func (c Chicken) GetName() string {
return c.Name
}
type Cat struct {
Name string
}
func (c Cat) Sing() {
fmt.Println(c.Name, "Sing")
}
func (c Cat) GetName() string {
return c.Name
}
/*
func sing(c Chicken) {
c.Sing() // 把Chicken 类型改为接口
}
*/
func sing(c SingInterface) {
c.Sing()
ch, static(状态) := c.(chicken) // 类型断言 或
switch name := c.(type){
case Chicken:
fmt.Println(name)
case Cat:
fmt.Println(name)
default:
fmt.Println("其他")
}
fmt.Println(c.GetName())
}
func main() {
c := Chicken{Name: "kunKun"}
ch := Cat{Name: "Mimi"}
sing(c)
sing(ch)
}
空接口
空接口可以接收任何类型
type name interface{}
func PrintZ(test interface{} ) {
fmt.Println(test)
}
泛型
泛型函数
func add[T int | float64 | int32](a, b T) T {
return a + b
}
泛型结构体
type Responsed[T any] struct {
Code int `json:"code"`
Msg string `json:"msg"`
Date T `json:"date"`
}
func main() {
type User struct {
Name string `json:"name"`
}
type UserInfo struct {
Name string `json:"name"`
Age int `json:"age"`
}
var userResponse Responsed[User]
var userInfoResponse Responsed[UserInfo]
json.Unmarshal([]byte(`{"code":0,"msg":"sure","date":{"name":"wood"}}`), &userResponse)
fmt.Println(userResponse.Date.Name)
json.Unmarshal([]byte(`{"code":0,"msg":"sure","date":{"name":"fake","age":18}}`), &userInfoResponse)
fmt.Println(userInfoResponse.Date.Name, userInfoResponse.Date.Age)
}
四:terminal 操作
- 格式化代码
gofmt –w .go 格式化并覆盖
gofmt -r '(a) -> a' –w *.go 将code中的 (a) 替换为 a
- 查看代码文档
go doc package xx函数 可以查看具体包 具体函数用法
- 安装第三方包
go install
- 升级版本
go fix
- 单元测试
测试文件命名为 xxx_test.go
go test
五: 函数
首字母大写可被外部调用
返回零值(或 nil)和 false 表示失败
// 有参有返回值的
func test(Datatype parameter)(return_datatype,return_datatype){
// code.......
return value,values
]
// 优先级 >> main 函数
// 初始化函数
func init() {
}
// 引用传递
func DoSomething(a *A) {
b = a // 通过指针传递,原始对象可以被修改,且 b 持有有效的指针引用。
}
func DoSomething(a A) {
b = &a // 通过值传递,原始对象不会被修改
}
// 多个重复参数
func add(numberList ...int){
}
// 署名函数
func {
var getName = func() (name string) {
name = "wood"
return
}
fmt.Println(getName())
}
go func() { ... }()
高阶函数
// _是函数名 == fun的名称 -> 1,2,3
var funMap = map[int]func _ (){
1: login,
2: register,
3: exit,
}
fun, ok := funMap[index]
if ok{
fun()
}
闭包
func AwaitAdd(awaitSecond int) func(...int) int {
{
return func(numberList ...int) (sum int) {
for _, number := range numberList {
sum += number
}
return sum
}
}
}
defer 函数
return 之前执行
距离return近谁先执行
用作与资源清理
在函数体执行完毕后再执行
六 : 流程控制
1. 条件
// 可以直接初始化变量用
if err := file.Chmod(0664); err != nil {
fmt.Println(err)
return err
}
switch var1 {
case var1:
// code
case var2:
// code2
fallthrough;
// 执行当前的接着执行下一个
case var3:
// code3
default:
}
2.循环
continue : 忽略剩余的循环体而直接进入下一次循环
Tag :标签功能 大写
LABEL1:
for i := 0; i <= 5; i++ {
for j := 0; j <= 5; j++ {
if j == 4 {
continue LABEL1
// continue 指向LABEL1 跳转执行该标签内容
}
fmt.Printf("i is: %d, and j is: %d\n", i, j)
}
}
}
for i := 0; i < 5; i++ {
// code
}
for i, j := 0, N; i < j; i, j = i+1, j-1 {}
for i:=0; i<5; i++ {
for j:=0; j<10; j++ {
println(j)
}
}
// 无条件循环 == while
for{}
// for-range == foreach
// 遍历
str := "Go is a beautiful language!"
fmt.Printf("The length of str is: %d\n", len(str))
for pos, char := range str {
fmt.Printf("Character on position %d is: %c \n", pos, char)
// pos 是index索引 char 指向的内容
for index, rune := range str2 {
fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune)))
七: 多线程
var wait sync.WaitGroup
func main() {
starttime := time.Now()
wait.Add(3)
go shopping("wood", &wait)
go shopping("fuck", &wait)
go shopping("cat", &wait)
wait.Wait()
fmt.Println("完成购买", time.Since(starttime))
}
func shopping(name string, wait *sync.WaitGroup) {
fmt.Printf("%s 开始购物\n", name)
time.Sleep(1 * time.Second)
fmt.Printf("%s 结束\n", name)
wait.Done()
}
channer 信道
var waat sync.WaitGroup
var moneyChan = make(chan int)
func main() {
starttime := time.Now()
waat.Add(3)
go pay("wood", 2, &waat)
go pay("fuck", 5, &waat)
go pay("cat", 3, &waat)
go func() {
waat.Wait()
close(moneyChan)
}()
for true {
money, ok := <-moneyChan
fmt.Println(money, ok)
if !ok {
break
}
}
// or
for money := range moneyChan {
fmt.Println(money)
}
fmt.Println("完成购买", time.Since(starttime))
}
func pay(name string, money int, wait *sync.WaitGroup) {
fmt.Printf("%s 开始购物\n", name)
time.Sleep(1 * time.Second)
fmt.Printf("%s 结束\n", name)
moneyChan <- money
waat.Done()
}
select
var waat1 sync.WaitGroup
var moneyChan1 = make(chan int)
var nameChan = make(chan string)
var doneChan = make(chan struct{})
func main() {
starttime := time.Now()
waat1.Add(3)
go send("wood", 2, &waat1)
go send("fuck", 5, &waat1)
go send("cat", 3, &waat1)
go func() {
defer close(moneyChan1)
defer close(nameChan)
defer close(doneChan)
waat1.Wait()
}()
var moneyList []int
var nameList []string
var event = func() {
for {
select {
case money := <-moneyChan1:
moneyList = append(moneyList, money)
case name := <-nameChan:
nameList = append(nameList, name)
case <-doneChan:
return
}
}
}
event()
fmt.Println("完成购买", time.Since(starttime))
fmt.Println(nameList)
fmt.Println(moneyList)
}
超时处理 Timeout
var done = make(chan struct{})
func event() {
fmt.Println("event开始执行")
time.Sleep(2 * time.Second)
fmt.Println("event执行完毕")
close(done)
}
func main() {
go event()
select {
case <-done:
fmt.Println("协程执行完毕")
case <-time.After(1 * time.Second):
fmt.Println("超时")
return
}
}
线程安全 lock
var sum2 int
var lock sync.Mutex
var wait2 sync.WaitGroup
func add1() {
lock.Lock()
for i := 0; i < 10000; i++ {
sum2++
}
lock.Unlock()
wait2.Done()
}
func sub1() {
lock.Lock()
for i := 0; i < 10000; i++ {
sum2--
}
lock.Unlock()
wait2.Done()
}
func main() {
wait2.Add(2)
go add1()
go sub1()
wait2.Wait()
fmt.Println(sum2)
}
Map.sync
var wait6 sync.WaitGroup
var mp1 sync.Map
func read() {
for {
fmt.Println(mp1.Load("time"))
}
wait6.Done()
}
func writer1() {
for {
mp1.Store("time", time.Now().Format("2006-01-02 15:04:05"))
}
wait6.Done()
}
func main() {
wait6.Add(2)
go read()
go writer1()
wait6.Wait()
}
八 : 异常处理
向上抛
func div(a, b int) (res int, err error) {
if b == 0 {
err = errors.New("division by zero")
return
}
res = a / b
return
}
func server() (res int, err error) {
res, err = div(10, 0)
if err != nil {
return
}
res++
res += 2
return
}
func main() {
res, err := server()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res)
}
中断程序
func init() {
_, err := os.ReadFile("dddd")
if err != nil {
println("error")
}
}
func main() {
fmt.Println("hello world")
}
恢复程序
func reading() {
defer func() {
err := recover()
if err != nil {
fmt.Println(err)
fmt.Println(string(debug.Stack()))
}
}()
var list []int = []int{1, 2}
fmt.Println(list[1])
}
func main() {
reading()
fmt.Println("正常执行")
}
IX. 文件流
1. FileRead
一次性读取
func ReadAtOnce() {
file, err := os.ReadFile("E:\\code\\go\\file\\text.txt")
if err != nil {
println(error.Error(err))
}
fmt.Println(string(file))
}
分片读取
func ShardReading() {
file, err := os.Open("E:\\code\\go\\file\\text.txt")
if err != nil {
panic(err)
}
defer file.Close()
for {
var byteData = make([]byte, 12)
n, err := file.Read(byteData)
if err == io.EOF {
break
}
fmt.Println(string(byteData[:n]))
}
}
缓冲读取
func BufRead() {
file, err := os.Open("E:\\code\\go\\file\\text.txt")
if err != nil {
panic(err)
}
defer file.Close()
buf := bufio.NewReader(file)
for {
text, _, err := buf.ReadLine()
if err == io.EOF {
break
}
fmt.Println(string(text))
}
}
缓冲选词
func BufRead2() {
file, err := os.Open("E:\\code\\go\\file\\text.txt")
if err != nil {
panic(err)
}
defer file.Close()
buf := bufio.NewScanner(file)
buf.Split(bufio.ScanWords)
var index int
for buf.Scan() {
index++
fmt.Println(index, buf.Text())
}
}
2. FileWrite
func main() {
file, err := os.OpenFile("w.txt", os.O_RDWR|os.O_CREATE, 0777)
if err != nil {
panic(err)
}
defer file.Close()
byteData, err := io.ReadAll(file)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(byteData))
err = os.WriteFile("w.txt", []byte("hi"), 0777)
fmt.Println(err)
file1, err1 := os.Open("C:\\Users\\34659\\Pictures\\117922308_p0_master1200.jpg")
if err1 != nil {
fmt.Println(err1)
return
}
defer file1.Close()
wfile, err2 := os.OpenFile("girl.jpg", os.O_WRONLY|os.O_CREATE, 0777)
if err2 != nil {
fmt.Println(err2)
return
}
defer wfile.Close()
io.Copy(wfile, file1)
}
X : 单元测试
文件要以 _test.go 为后缀
func TestAdd(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
t.Errorf("Add(1, 2) = %d; want 3", ans)
}
if num := Add(4, 5); num != 8 {
t.Errorf("Add(4,5) = %d; want 8", num)
}
子测试
func TestAdd(t *testing.T) {
t.Run("add1", func(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
t.Errorf("Add(1, 2) = %d; want 3", ans)
}
})
t.Run("add2", func(t *testing.T) {
if num := Add(4, 5); num != 8 {
t.Errorf("Add(4,5) = %d; want 8", num)
}
})
}
Log | 打印日志, 结束测试 | PASS |
---|---|---|
Logf | 格式化输出日志, 同时结束测试 | PASS |
Error | 打印错误日志,结束测试 | FAIL |
Errorf | FAIL | |
Fatal | 打印致命日志,同时结束 | FAIL |
FatalF | FAIL |
TestMain
func setup() {
fmt.Println("setup")
}
func teardown() {
fmt.Println("teardown")
}
func Test1(t *testing.T) {
fmt.Println("Test1")
}
func Test2(t *testing.T) {
fmt.Println("Test2")
}
func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}
XI.与其他语言进行交互
https://learnku.com/docs/the-way-to-go/interact-with-other-languages/3581
XII: 反射
判断类型
func refType(obj any) {
typeObj := reflect.TypeOf(obj)
fmt.Println(typeObj, typeObj.Kind())
tp := typeObj.Kind()
// 判断类型
switch tp {
case reflect.Slice:
fmt.Println("切片")
case reflect.Map:
fmt.Println("map")
case reflect.Struct:
fmt.Println("struct")
case reflect.String:
fmt.Println("string")
}
}
func main() {
refType(struct {
Name string
}{Name: "wood"})
name := "wood"
refType(name)
refType([]string{"wood"})
name1 := "风"
获取值
func reflectionGetValues(obj any) {
value := reflect.ValueOf(obj)
fmt.Println(value.Type())
switch value.Kind() {
case reflect.Int:
fmt.Println(value.Int())
case reflect.Struct:
fmt.Println(value.Interface())
case reflect.String:
fmt.Println(value.String())
}
}
func main(){
reflectionGetValues(44)
}
修改值
func reflectionSetValues(obj any) {
value := reflect.ValueOf(obj)
elem := value.Elem()
// 专门取指针反射的值
switch elem.Kind() {
case reflect.String:
elem.SetString("枫枫知道")
}
}
func main() {
reflectionSetValues(&name1)
fmt.Println(name1)
}
群友到此一游