这是我参与「第五届青训营 」笔记创作活动的第1天
本堂课重点内容:
- Go基础语法及几个常用的标准库
- 实战案例
- 猜谜游戏
- 在线词典
- SOCKS5代理
详细知识点介绍
基础语法
- Go变量的定义
```
var (
a = 1
b = true
c = "def"
)//批量定义变量
func variableZeroValue() {
var a int//使用var关键字定义变量
var s string
fmt.Println(a, s)
//空串不显示,换一种打印方式
fmt.Printf("%d %q\n", a, s)//0 ""
}
func variableInitialValue() {
var a, b int = 3, 4
var s string = "abc"
fmt.Println(a, b, s)
}
func variableTypeDeduction() {
var a, b, v, s = 3, 4, true, "def"
fmt.Println(a, b, v, s)
}
func variableShorter() { //在函数外面不能这样定义变量
a, b, v, s := 3, 4, true, "def"
fmt.Println(a, b, v, s)
}
func euler() { //golang内建变量有复数 complex64或者complex128
fmt.Printf("%.3f\n", cmplx.Pow(math.E, 1i*math.Pi)+1)
}
func triangle() { //golang中没有隐式类型转换,必须强制转换
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64((a*a + b*b))))
fmt.Println(c)
}
func consts() { //golang常量的定义
const (
fileename = "abc.txt"
a, b = 3, 4 //当我们没有规定类型是,在下面的使用时它会根据语句推断为float64
)
var c int = int(math.Sqrt(a*a + b*b))
fmt.Println(c)
}
func enums() { //枚举类型,使用const关键字定义
const (
cpp = 0
java = 1
)
fmt.Println(cpp, java)
//使用iota,从0开始自加
const (
a = 1 << (10 * iota)
b
_ //iota仍然会递增一次,只是没有使用
c
)
fmt.Println(a, b, c)
}
```
- Go中的循环和分支
Go语言中的分支语句和其他语言差不多,不同的是在if语句中判断的条件不用加括号(Go的语法中相对于其他语言很多地方都将括号省略了),而switch语句相对于其他语言就更为强大了,判断的值可以是任意类型,也可以不写,在case后写上判断条件,并且当一个case匹配后会直接跳出判断,不需要break语句。
```
func grade(score int) string {
g := ""
//golang中switch会自动break,除非使用fallthrough
switch { //switch后面可以没有表达式
case score < 0 || score > 100:
g = "wrong score"
case score < 60:
g = "不及格"
//fallthrough
default:
g = "及格"
}
return g
}
```
Go语言中的循环只有for,如果后面三条语句里面只保留一条就相当于while循环
- Go函数定义 与C相比,Go函数的返回值是后置的,并且可以返回多个
```
func div(a, b int) (int, int) {
return a / b, a % b
} //还可以像下面这样写,但是不推荐
//func div(a, b int) (q,r int) {
// q=a/b
// r=a%b
// return
//}
func sum(numbers ...int) int { //可变参数列表
s := 0
for i := range numbers {//Go迭代遍历
s += numbers[i]
}
return s
}
func swap(a, b *int) {//没有返回值时直接省略,不需要void
*a, *b = *b, *a
}
```
- 结构体定义
```
type treeNode struct {
value int
left, right *treeNode
}
```
- 数组、切片、map Go里面数组用的比较少,大部分时间都是使用切片 数组
```
//注意,数组是值类型,在函数里面操作数组的值,原数组的值不能改变
func main() {
var arr1 [5]int
arr2 := [3]int{1, 3, 5} //这样定义要负初值
arr3 := [...]int{2, 3, 4, 5}
var grid [4][5]int
fmt.Println(arr1, arr2, arr3)
fmt.Println(grid)
//遍历数组
for i := 0; i < len(arr3); i++ {
fmt.Print(arr3[i])
}
fmt.Printf("\n")
//使用range遍历数组
for i := range arr3 {
fmt.Print(arr3[i])
}
fmt.Printf("\n")
//同时获得下标和值
for i, v := range arr3 {
fmt.Println(i, v)
}
}
```
切片
```
func main() {
var s []int //切片不是数组
for i := 0; i < 100; i++ {
printSlice(s)
s = append(s, 2*i+1)
}
fmt.Println(s)
s1 := []int{2, 4, 6, 8} //系统先建立一个长度为4的数组,然后再取一个view
fmt.Println(s1)
//当我们知道切片所需要的长度但不知道值时,可以使用make函数
s2 := make([]int, 16) //len==cap==16
s3 := make([]int, 10, 32) //len==10,cap==32
printSlice(s2)
printSlice(s3)
//copy slice
copy(s2, s1)
fmt.Println(s2)
printSlice(s2)
//删除元素
s2 = append(s2[:3], s2[4:]...)
fmt.Println(s2)
printSlice(s2)
}
```
map
```
func main() {
m1 := map[string]string{
"love": "han",
"1314": "wait",
}
var m2 map[string]int //empty map
m3 := make(map[string]int) //nil
fmt.Println(m1, m2, m3)
fmt.Println("Traversing map")
for k, v := range m1 {
fmt.Println(k, v)
} //打印出来的顺序是不一样的
fmt.Println("Getting values")
loveName := m1["love"] //如果我们取得key在map里没有,会返回一个空串
fmt.Println(loveName)
//处理map里找不到对应key的方法
if secondName, ok := m1["1314"]; ok {
fmt.Println(secondName)
} else {
fmt.Println("key does not exist")
}
fmt.Println("Deleting values")
fmt.Println(m1)
delete(m1, "1314")
fmt.Println(m1)
}
```
几个常用标准库
json库,主要是marshal和unmarshal方法 time库,和时间相关的一些方法 strconv库,和数字解析相关的一些方法 os/exec库,和进程相关的一些方法
实战案例
猜谜游戏
猜谜游戏其实就是平常玩的数字炸弹游戏
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
func main() {
var min, max int = 0, 100
var t, key int
rand.Seed(time.Now().UnixNano()) //不做这部处理的话每次随机数都是相同的
key = rand.Intn(100)
fmt.Printf("key: %v\n", key)
for {
fmt.Println("请输入你猜的数字")
fmt.Scanf("%d", &t)
switch {
case t > key:
max = t
fmt.Printf("你猜大了,现在的范围是%d到%d之间\n", min, max)
case t < key:
min = t
fmt.Printf("你猜小了,现在的范围是%d到%d之间\n", min, max)
default:
fmt.Println("你猜中了")
os.Exit(0)
}
}
}
在线词典
我们自己向服务器发送请求,然后处理返回的json数据,增加另外一个翻译器支持并使用goroutine并发获取数据。 使用的代码生成工具:[json转struct](在线工具 - OKTools)、[通过curl command生成Go代码](Convert curl to Go (curlconverter.com))
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"sync"
)
var wg sync.WaitGroup
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
}
type DictResponse struct {
Rc int `json:"rc"`
Wiki struct {
KnownInLaguages int `json:"known_in_laguages"`
Description struct {
Source string `json:"source"`
Target interface{} `json:"target"`
} `json:"description"`
IsSubject string `json:"is_subject"`
Item struct {
Source string `json:"source"`
Target string `json:"target"`
} `json:"item"`
ImageURL string `json:"image_url"`
Sitelink string `json:"sitelink"`
ID string `json:"id"`
} `json:"wiki"`
Dictionary struct {
Prons struct {
EnUs string `json:"en-us"`
En string `json:"en"`
} `json:"prons"`
Explanations []string `json:"explanations"`
Synonym []string `json:"synonym"`
Antonym []string `json:"antonym"`
WqxExample [][]string `json:"wqx_example"`
Entry string `json:"entry"`
Type string `json:"type"`
Related []interface{} `json:"related"`
Source string `json:"source"`
} `json:"dictionary"`
}
func Query(word string) {
defer wg.Done()
client := &http.Client{}
// var data = strings.NewReader(`{"trans_type":"zh2en","source":"喜欢"}`)
// word:="love"
dictRequest := DictRequest{"en2zh", word}
b, err2 := json.Marshal(dictRequest)
if err2 != nil {
fmt.Println("序列化json数据出错")
}
data := bytes.NewReader(b)
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("authority", "api.interpreter.caiyunai.com")
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Microsoft Edge";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
req.Header.Set("sec-fetch-dest", "empty")
req.Header.Set("sec-fetch-mode", "cors")
req.Header.Set("sec-fetch-site", "cross-site")
req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != 200 {
fmt.Println("error,返回的StatusCode为", resp.StatusCode)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
// fmt.Printf("%s\n", bodyText)
var dictResponse DictResponse
err3 := json.Unmarshal(bodyText, &dictResponse) //传地址,否则写入不进去
if err3 != nil {
fmt.Println("返回的数据反序列化失败")
}
// fmt.Printf("dictResponse: %#v\n", dictResponse)
fmt.Println("来自彩云小译的结果:")
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
}
type DictResponseByBaidu struct {
TransResult struct {
Data []struct {
Dst string `json:"dst"`
PrefixWrap int `json:"prefixWrap"`
Result [][]interface{} `json:"result"`
Src string `json:"src"`
} `json:"data"`
From string `json:"from"`
Status int `json:"status"`
To string `json:"to"`
Type int `json:"type"`
Phonetic []struct {
SrcStr string `json:"src_str"`
TrgStr string `json:"trg_str"`
} `json:"phonetic"`
} `json:"trans_result"`
DictResult struct {
Edict struct {
Item []struct {
TrGroup []struct {
Tr []string `json:"tr"`
Example []string `json:"example"`
SimilarWord []string `json:"similar_word"`
} `json:"tr_group"`
Pos string `json:"pos"`
} `json:"item"`
Word string `json:"word"`
} `json:"edict"`
Collins struct {
Entry []struct {
EntryID string `json:"entry_id"`
Type string `json:"type"`
Value []struct {
MeanType []struct {
InfoType string `json:"info_type"`
InfoID string `json:"info_id"`
Example []struct {
ExampleID string `json:"example_id"`
TtsSize string `json:"tts_size"`
Tran string `json:"tran"`
Ex string `json:"ex"`
TtsMp3 string `json:"tts_mp3"`
} `json:"example"`
} `json:"mean_type"`
Gramarinfo []struct {
Tran string `json:"tran"`
Type string `json:"type"`
Label string `json:"label"`
} `json:"gramarinfo"`
Tran string `json:"tran"`
Def string `json:"def"`
MeanID string `json:"mean_id"`
Posp []struct {
Label string `json:"label"`
} `json:"posp"`
} `json:"value"`
} `json:"entry"`
WordName string `json:"word_name"`
Frequence string `json:"frequence"`
WordEmphasize string `json:"word_emphasize"`
WordID string `json:"word_id"`
} `json:"collins"`
From string `json:"from"`
SimpleMeans struct {
WordName string `json:"word_name"`
From string `json:"from"`
WordMeans []string `json:"word_means"`
Exchange struct {
WordThird []string `json:"word_third"`
WordIng []string `json:"word_ing"`
WordDone []string `json:"word_done"`
WordPl []string `json:"word_pl"`
WordPast []string `json:"word_past"`
} `json:"exchange"`
Tags struct {
Core []string `json:"core"`
Other []string `json:"other"`
} `json:"tags"`
Symbols []struct {
PhEn string `json:"ph_en"`
PhAm string `json:"ph_am"`
Parts []struct {
Part string `json:"part"`
Means []string `json:"means"`
} `json:"parts"`
PhOther string `json:"ph_other"`
} `json:"symbols"`
} `json:"simple_means"`
Lang string `json:"lang"`
Oxford struct {
Entry []struct {
Tag string `json:"tag"`
Name string `json:"name"`
Data []struct {
Tag string `json:"tag"`
Data []struct {
Tag string `json:"tag"`
P string `json:"p"`
PText string `json:"p_text"`
} `json:"data"`
} `json:"data"`
} `json:"entry"`
Unbox []struct {
Tag string `json:"tag"`
Type string `json:"type"`
Name string `json:"name"`
Data []struct {
Tag string `json:"tag"`
Text string `json:"text,omitempty"`
Words []string `json:"words,omitempty"`
Outdent string `json:"outdent,omitempty"`
Data []struct {
Tag string `json:"tag"`
EnText string `json:"enText"`
ChText string `json:"chText"`
} `json:"data,omitempty"`
EnText string `json:"enText,omitempty"`
ChText string `json:"chText,omitempty"`
} `json:"data"`
} `json:"unbox"`
} `json:"oxford"`
Sanyms []struct {
Tit string `json:"tit"`
Data []struct {
P string `json:"p"`
D []string `json:"d"`
} `json:"data"`
Type string `json:"type"`
} `json:"sanyms"`
Usecase struct {
Collocation struct {
Data []struct {
P string `json:"p"`
Ex []struct {
En string `json:"en"`
Zh string `json:"zh"`
} `json:"ex"`
} `json:"data"`
Desc string `json:"desc"`
} `json:"collocation"`
Idiom []struct {
P string `json:"p"`
Tag string `json:"tag"`
Data []struct {
Tag string `json:"tag"`
Data []struct {
EnText string `json:"enText"`
Tag string `json:"tag"`
ChText string `json:"chText"`
} `json:"data"`
Xt string `json:"xt,omitempty"`
} `json:"data"`
} `json:"idiom"`
} `json:"usecase"`
Synonym []struct {
Synonyms []struct {
Tips string `json:"tips"`
Bx string `json:"bx"`
Syn struct {
P string `json:"p"`
Word string `json:"word"`
D []string `json:"d"`
} `json:"syn"`
Ex []struct {
EnText string `json:"enText"`
ChText string `json:"chText"`
} `json:"ex"`
} `json:"synonyms"`
Guide string `json:"guide"`
Words []string `json:"words"`
} `json:"synonym"`
BaiduPhrase []struct {
Tit []string `json:"tit"`
Trans []string `json:"trans"`
} `json:"baidu_phrase"`
} `json:"dict_result"`
LijuResult struct {
Double string `json:"double"`
Tag []string `json:"tag"`
Single string `json:"single"`
} `json:"liju_result"`
Logid int `json:"logid"`
}
func QueryByBaidu(word string) {
defer wg.Done()
client := &http.Client{}
dateReader := `from=en&to=zh&query=` + word + `&transtype=translang&simple_means_flag=3&sign=198772.518981&token=de0de4ea09af4dd20d455ac7aa269fb0&domain=common`
var data = strings.NewReader(dateReader)
req, err := http.NewRequest("POST", "https://fanyi.baidu.com/v2transapi?from=en&to=zh", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept", "*/*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
req.Header.Set("Acs-Token", "1673856314151_1673861704496_5nfnvniCGuXKn17dtB6RTyrRRI9R/oBRE0HDY6EvG3Dj35U1s9t37gbU7Nec5lgZi7FMcCYhoiz/GLHPT27sHyTqHJfDm4im8j1ELWemPJV4/DBlVF1n268/AumjZR56NdVydZuEfB9R9MPkscIvjjz/nULoFwpOAcISbQdAtB248SdcCH/5SxBhdMKLutOuaFVdeIzphWUfqBCxygXWVXhp4uIbCuNtt7D3jO9AqbLFImV/IIx2FSIezb3DN8JwSu5DNPEvxV/nZYh1qo+MCyDZq/grltsahEbZtnwQTa3htOioxeKE4JVvFJE8E+NOCaNTx9IxSDwffKFqIXiMPg==")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("Cookie", "BAIDUID=B55A4DC651D1A0B9042B8F8C23B03416:FG=1; BAIDUID_BFESS=B55A4DC651D1A0B9042B8F8C23B03416:FG=1; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BIDUPSID=B55A4DC651D1A0B9042B8F8C23B03416; PSTM=1671683094; ZFY=OqJz2n:AhY1EfwdFdC:AAZIUJMbGurE9NH2EG35hwu:Ac8:C; __bid_n=185482736aee8ad5b34207; FEID=v10-5a44b605f95016ea3af95dd6eb86a68f1d4feeb9; __xaf_fpstarttimer__=1672130803245; __xaf_thstime__=1672130804655; __xaf_fptokentimer__=1672130804658; FPTOKEN=QCBDwd99wGK387CJ2fEAMjKUu2B6Jl0WRh/cs9QEkDo4D0L+y8jJEdeqnzehedtRafrHuDfkC8m+/zWpAFBa9xxP5ZySpQGQ1lKS3RF9ivTY/y7QA9zb8rrGPgH9loSkX8cWJbf5u0K33yhsQ1wbI6OM8q8RUoIOsIVBEIbktQ08iD8YrJpVPBTLMmriQGpcdBVguL0TA6g9yU9Fc8+e2KE3pMQ1RKvQBWyAZsb8G301fxTlLJEDjUaEVapDGv/iipIToiei6i1oMpgmWOzR01cJccJPPsWp9bHa8xNUFeexHqSS0NI6S1LivykqBmIlB/f9aJ4FV7umPq2J48WwgRWk2CCD+Q+Esc+iFVE8LWTqBQvbp2B215zFIrxbcDbNGwUm4d3UMcgM8WfocVUDOw==|L+ur0ygOSzGV1UuicuyBy6h7GNMTEUtcZseLBYemJPg=|10|64a2c0498b99d62da72900a80389bcdc; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1672659396,1672719233,1673067930,1673861578; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1673861578; ab_sr=1.0.1_MmU2M2Q1ODJhYzhhYzFhOTdmN2FjMWZiNGVjZGRkNDQyNzMwN2E1ZDkwYzkwOGZmM2ZlMzJiYTNhYzMwMDFhYzhiNGY5ODRlYmVlNjBhYzE3YjBkOTQ5YmE0Y2ZjOWE1ODJmOTEwZTc2NDhmYjY5ZWJjMGExYzA1YTQ4OTIxYjgzOTk1Y2Y5YjE2NTc1NGFmMzM2OTk1ODdhZDUxNzBmYQ==")
req.Header.Set("Origin", "https://fanyi.baidu.com")
req.Header.Set("Referer", "https://fanyi.baidu.com/")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76")
req.Header.Set("X-Requested-With", "XMLHttpRequest")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Microsoft Edge";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
// fmt.Printf("%s\n", bodyText)
var dictResponseByBaidu DictResponseByBaidu
err2 := json.Unmarshal(bodyText, &dictResponseByBaidu)
if err2 != nil {
fmt.Println("返回的数据反序列化失败")
}
// fmt.Printf("dictResponse: %#v\n", dictResponseByBaidu)
fmt.Println("来自百度翻译的结果:")
for _, item := range dictResponseByBaidu.DictResult.SimpleMeans.WordMeans {
fmt.Println(item)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Println("请传入需要查询的单词")
os.Exit(1)
}
wg.Add(2)
var word string = os.Args[1]
go Query(word)
go QueryByBaidu(word)
wg.Wait() //等待执行完成再退出程序
}
SOCKS5代理
由于这个练习背后涉及的知识和代码较复杂,这篇文章篇幅也已经较长了,所以会在后面重新写一篇文章来记录。