Go语言实例|青训营笔记

97 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

今天对之前课程中的Go语言实例进行了复习和笔记补充

实例1:猜数字

rand.Seed(time.Now().UnixNano())使用当前时间戳(纳秒,Unix()是秒)设定种子

secretNumber := rand.Intn(maxNum) Intn是math/rand包下[0,maxNum)随机生成数字,不选种子则默认相同的序列

版本1:使用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 {

       n, err := fmt.Scanf("%d\n", &guess) //不'\n'会将回车读入下一次循环

       if err != nil {                     //查看输入字母或上面Scanf没有\n是什么样子

           fmt.Println("读取成功", n, "个,错误是", err)

       }

       fmt.Println("You guess is", guess)

       if guess > secretNumber {

           fmt.Println("bigger")

       } else if guess < secretNumber {

           fmt.Println("smaller")

       } else {

           fmt.Println("Correct")

           break

       }

    }

}

版本2:使用bufio对象(带缓存io)

r := bufio.NewReader(file)

n, err := r.Read(buf),n是读取到的长度,for循环读取直到n==0即读取完整个文件

func (b *Reader) ReadString(delim byte) (string, error) 以delim为分隔符,从bufio对象中读取一个

input = strings.Trim(input, "\r\n")剪掉input头尾的"\r\n"字符串(注意这里win的回车是\r\n) (见仓库源码)

实例2:命令行在线词典,发送http请求

fanyi.caiyunapp.com的开发者工具name=dict中的method=POST(payload和preview是翻译信息)

右键复制请求copy as cURL(bash),到curlconverter.com,生成go语言 func main() {

    client := &http.Client{} //创建httpclient对象

   var data = strings.NewReader({"trans_type":"en2zh","source":"good"})

    //创建http请求对象,其中将请求信息保存在data这个流中

    req, err := http.NewRequest("POST", "api.interpreter.caiyunai.com/v1/dict", data)

    if err != nil {

       log.Fatal(err)

    }

    req.Header.Set("Connection", "keep-alive")

    (许多req.请求头部,删除也行)

    resp, err := client.Do(req)  //发起请求

    if err != nil {

       log.Fatal(err)

    }

    defer resp.Body.Close()

    bodyText, err := ioutil.ReadAll(resp.Body) //将回应读取为json到字符串里

    if err != nil {

       log.Fatal(err)

    }

    fmt.Printf("%s\n", bodyText)

}

 

下面生成自己的request body

//创建json结构体

type DictRequest struct {

    TransType string json:"trans_type"

    Source    string json:"source"

    UserID    string json:"user_id"

}

 

func main() {

    client := &http.Client{}

    request := DictRequest{TransType: "en2zh", Source: "good"}

    buf, err := json.Marshal(request)    //将json结构体序列化成json字符串

    if err != nil {

       log.Fatal(err)

    }

    var data = bytes.NewReader(buf)  //json字符串转成bytes的reader流

    req, err := http.NewRequest("POST", "api.interpreter.caiyunai.com/v1/dict", data)

    if err != nil {

       log.Fatal(err)

    }

 

返回的反序列化(提取音标、解释等)

oktools.net/json2go,从json转换成json结构体

defer resp.Body.Close()

bodyText, err := ioutil.ReadAll(resp.Body)

if err != nil {

    log.Fatal(err)

}

var dictResponse DictResponse

err = json.Unmarshal(bodyText, &dictResponse)

if err != nil {

    log.Fatal(err)

}

//fmt.Printf("%#v\n", dictResponse)

fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)

for _, item := range dictResponse.Dictionary.Explanations {

    fmt.Println(item)

}

另外,返回的请求还要验证是否是状态码200正常返回

if resp.StatusCode != 200 {

       log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))

    }

最后完善,从命令读取单词

 

实例3:socks5代理服务器

 

1:协商版本,是否认证(这里无认证)

2、3:和想访问的地址连接、传输数据

 

首先先写一个tcp echo服务器(tcp服务器接收简单数据并回复原文)

func main() {

    server, err := net.Listen("tcp", "127.0.0.1:1080")     //监听端口

    if err != nil {

       panic(err)

    }

    //循环接收tcp连接

    for {

       client, err := server.Accept()

       if err != nil {

           log.Printf("Accept failed %v", err)

           continue

       }

       //go启动goroutine,处理连接

       go process(client)

    }

}

 

func process(conn net.Conn) {

    defer conn.Close()

    reader := bufio.NewReader(conn)

    for {

       b, err := reader.ReadByte() //从缓冲流中读一个字节

       if err != nil {

           break

       }

       //向客户端回复一个字节,[]byte是元素是字节的一个切片

       //[]byte不能比较,性能较好,适用于切片操作,string不能为nil,

       _, err = conn.Write([]byte{b})

       if err != nil {

           break

       }

    }

}