题记
这是我参与「第五届青训营 」伴学笔记创作活动的第 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 int
for {
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。
另一个结构体就不说了,注意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,后面就是错误处理,状态码对不对,然后输出数据。
两个翻译引擎
百度翻译的api
"http://api.fanyi.baidu.com/api/trans/vip/translate"
proxy
先看connect函数吧,首先看参数提供一个bufio.Reader(利用一个缓冲区,在底层文件读取器和读操作方法间架起了桥梁。底层文件读取器就是初始化 Reader 的时候需要传入的io.Reader。有这样一个缓冲区的好处是,每次我们想读取文件内容时,会首先从缓冲区读取,提高了读取速度,也避免了频繁的 文件IO,同时必要时会利用底层文件读取器提前加载部分数据到缓冲区中,做到未雨绸缪),另一个提供了Conn接口里面有许多method。
然后我们看函数内部,首先buf := make([]byte, 4)我们创建了一个字符切片,len为4。
_, err = io.ReadFull(reader, buf) 改函数读取len(buf)的bytes从reader,传递给buf。返回值为多少个被copy的字节数和error
函数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个old
time.Now().Unix() // unix 时间戳 从1970年到现在有多少秒
t2.Sub(t) //t2-t的时间差
strconv.Atoi() //string转int,会失败,返回值有err,可以用于判断是否转化成功
os.Args //cmd中的输入