这是我参与「第五届青训营 」伴学笔记创作活动的第 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
}
}
}