day1 go基础| 青训营笔记

201 阅读2分钟

题记

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天,本文用于记录在青训营的学习笔记和一些心得。

day1 1月15日

Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。

前面的基础部分建议观看blog中的黑马程序员那篇里面很详细:Go黑马程序员(国内可能加载比较慢,如果加载不出来,掘金找我,我给你md文件),基础的话书籍方面推荐Go语言学习笔记(相信我,圣经你把握不住的),我们直接来看实战的三个项目。

guessing-game

首先定义一个随机数的最大值maxNum为100,然后使用rand.Seed(time.Now().UnixNano())(不同的种子生成不同的随机数,无种子编译后运行的结果是定值。通常以时钟作为参数初始化)

关于 rand.Seed(time.Now().UnixNano())

然后使用 rand.Intn(maxNum),注意这个随机数是不可能为100的,值为[0,100) ,准备输入你guess的值,reader := bufio.NewReader(os.Stdin) ——>NewReader创建读缓冲区,然后从标准输入生成读对象。进入循环, reader.ReadString('\n'): 读取'\n'之前的所有string数据。如果err不为空,说明读取失败,进入下一次循环。如果为nil,继续走下去,input = strings.Trim(input, "\r\n")这句话是指,删除input开头结尾的"\r\n"。因为你输入的string,Atoi函数转成int,(由于 string 可能无法转换为int,所以这个函数有两个返回值:第一个返回值是转换成 int 的值,第二个返回值判断是否转换成功),所以先判断转化是否成功,然后比较大小,如果猜的不对,继续循环。

scanf版本

package main
​
import (
    "fmt"
    "math/rand"
    "time"
)
​
func main() {
    maxNum := 100
    rand.Seed(time.Now().UnixNano())
    secretNumber := rand.Intn(maxNum)
    // fmt.Println("The secret number is ", secretNumber)
​
    fmt.Println("Please input your guess")
    var guess intfor {
        fmt.Scanf("%d\n", &guess)  //不'\n'会打印两遍语句
        fmt.Println("You guess is", guess)
        if guess > secretNumber {
            fmt.Println("Your guess is bigger than the secret number. Please try again")
        } else if guess < secretNumber {
            fmt.Println("Your guess is smaller than the secret number. Please try again")
        } else {
            fmt.Println("Correct, you Legend!")
            break
        }
    }
}

simpledict

先定义一个结构体DictRequest,里面包含三个字符串变量TransType ,Source ,UserID。

image-20230115155931147

另一个结构体就不说了,注意interface{} 类型:空接口,是导致很多混淆的根源。interface{} 类型是没有方法的接口。由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口。这意味着,如果您编写一个函数以 interface{} 值作为参数,那么您可以为该函数提供任何值。

反正这两个结构体都不是我们自己要动手写的。(JSON转Golang Struct

然后我们来讲讲query函数,先看定义传入一个string参数,无返回值。然后我们看函数的内部实现,首先我们自定义一个http客户端实例(client=&http.Client{}),然后定义一个结构体实例,request := DictRequest{TransType: "en2zh", Source: word},注意该结构体有三个变量,我们这里只是定义二个(这一步是将翻译内容传入结构体)。buf, err := json.Marshal(request) 进行对request的编码,我们json还提供一种编码方式json.NewEncoder().Encode(),这里不做讲解,感兴趣自己上网搜索。判断err。bytes.NewReader(buf):创建Reader。

http.NewRequest:post请求url,数据为data

req.Header.Set()请求头参数设置

client.do(req) 发送http请求,并得到响应数据

defer resp.Body.Close() 延迟close响应头,query函数结束执行

io.ReadAll(resp.Body):ReadAll读取resp.Body里的全部数据

之后就是定义一个存储响应数据的结构体,解码bodyText,后面就是错误处理,状态码对不对,然后输出数据。

image-20230115163322203

两个翻译引擎

百度翻译的api
"http://api.fanyi.baidu.com/api/trans/vip/translate"

proxy

先看connect函数吧,首先看参数提供一个bufio.Reader(利用一个缓冲区,在底层文件读取器和读操作方法间架起了桥梁。底层文件读取器就是初始化 Reader 的时候需要传入的io.Reader。有这样一个缓冲区的好处是,每次我们想读取文件内容时,会首先从缓冲区读取,提高了读取速度,也避免了频繁的 文件IO,同时必要时会利用底层文件读取器提前加载部分数据到缓冲区中,做到未雨绸缪),另一个提供了Conn接口里面有许多method。

image-20230115185433881

然后我们看函数内部,首先buf := make([]byte, 4)我们创建了一个字符切片,len为4。

_, err = io.ReadFull(reader, buf) 改函数读取len(buf)的bytes从reader,传递给buf。返回值为多少个被copy的字节数和error

image-20230115190140654

image-20230115191326447

image-20230115191753071

image-20230115192626541

函数auth,process就不讲了吧。。。

并行翻译引擎

go两个不就行了,还是我太笨没看懂,喵喵喵。

ch := make(chan int)
go func() {
	query(word, ch)
}()
<-ch

    query(word string,ch chan int){
        defer close(ch)
    }
    
    var wg sync.WaitGroup
wg.Add(2)
go query(word, &wg)
go query2(word, &wg)
wg.Wait()

补充点基础的知识

主要补充一些自己容易忘的东西吧

delete(map,key) //删除根据key,删除map里对应的key-value键值对、fmt.Println(strings.Replace(a, "e", "E", -1))         //n<0,比如-1,替代所有old
fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2)) //n>0,比如2,替代2个oldtime.Now().Unix() // unix 时间戳 从1970年到现在有多少秒t2.Sub(t) //t2-t的时间差strconv.Atoi() //string转int,会失败,返回值有err,可以用于判断是否转化成功os.Args //cmd中的输入