Go语言基础语法(2) | 青训营笔记

75 阅读3分钟

``

猜谜游戏


maxNum := 100  
secretNumber := rand.Intn(maxNum)  
fmt.Println("秘密数字为", secretNumber)  
fmt.Println("请输入你猜的数字")  

reader := bufio.NewReader(os.Stdin)
//用这个方法读取进程文件
for {

input, err := reader.ReadString('\n')  //读取到换行符停止,并保存给input
if err != nil {  
fmt.Println("读取内容出现了错误", err)  
return  
}  
  
input = strings.TrimSuffix(input, "\n")  // !!!!!!!!注意
input = strings.TrimSuffix(input, "\r") //
  
guess, err2 := strconv.Atoi(input)  
if err2 != nil {  
fmt.Println("不合法输入,请输入整形数值", err2)  
return  
}  
  
if guess > secretNumber {  
fmt.Println("太大啦,重新输入一下吧")  
continue  
} else if guess < secretNumber {  
fmt.Println("太小啦,重新输入一下吧")  
continue  
} else {  
fmt.Println("猜对啦,答案就是", guess)  
break  
}
}

由于回车提交 windows平台会在后面加上\r\n Linux平台则是\n, 会在后面加\r\n 需要用这个方法删除 input = strings.TrimSuffix(input, "\n") input = strings.TrimSuffix(input, "\r")

var guess int  
maxNum := 100  
secretNumber := rand.Intn(maxNum)  
fmt.Println("秘密数字为", secretNumber)  
fmt.Println("请输入你猜的数字")   
  
for {  
_, err := fmt.Scanf("%d\n", &a)  
//这里注意一下"%d\n",如果 fmt.Scanf方法读取到\n换行符,会报错
if err != nil {  
fmt.Println(err)  
return  
}  
.
.
//下面一样

简化后

命令行词典

该怎么用go语言来发送HTTP请求,调用第三方的API将查询到的单词翻译出来,再用解析json过来呢

首先右击网页空白处,打开检查,然后打开network,清空请求,再点击翻译,找到api请求,右击请求copy as cURL,之后在curlconverter.com/go/ 一键生成代码 copy到Goland中

type DictRequest struct {  
TransType string `json:"trans_type"` //翻译语言  
Source string `json:"source"` //翻译内容  
UserID string `json:"user_id"`  

client := &http.Client{}  
request := DictRequest{TransType: "en2zh", Source: "good"}  
buf, err := json.Marshal(request)  //将固定报文修改成自己设置的  
if err != nil {  
log.Fatal(err)  
}  
var data = bytes.NewReader(buf)  //将之存到data里
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/translator", data)     
//将这个data发送出去
req.Header.Set(..) //一些请求头
.
.
}

在go里面并不推荐把响应体放在map里,去取值的。应该用一个结构体,把返回来的json反序列化到结构体中 oktools.net/json2go 用这个网址可以快速创建结构体.(如果不会对这个返回操作不做更多的精细化操作,可以用嵌套)

resp, err := client.Do(req)  
if err != nil {  
log.Fatal(err)  
}  
defer resp.Body.Close()  //go语言编程习惯,为避免资源泄露,用defer关闭流
  
bodyText, err := io.ReadAll(resp.Body)  //拿到返回的json
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)

现在还不能灵活的翻译,所以可以将这些代码放入写进一个函数通过传入单词参数,来实现翻译功能


if resp.StatusCode != 200 {  
log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))  
}   //防止报错 
  
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)  
for _, item := range dictResponse.Dictionary.Explanations {  
fmt.Println(item)  //将结构体中需要显示的值更改清晰的打印出来
}

log.Fatal()会立即终止程序并输出错误信息 panic()会产生一个异常并让程序崩溃,但是可以在调用的地方进行处理。 将上面合起来放入一个函数中去 func query(word string) {}

SOCKS5代理服务器

在防火墙里开了个口子,让授权的用户通过单个端口可以访问左右的资源。
写爬虫时,防止IP访问频率超过限制报错,可用代理ip池(其中很多代理协议就是socks5协议)解决

原理图

683b3054-0702-48cb-bb0b-8749663b5202.png

tcp echo server

源代码hi-hi.cn/go

func main() {
	server, err := net.Listen("tcp", "127.0.0.1:1080") //侦听端口,返回server
	if err != nil {
		panic(err)
	}
	for {
		client, err := server.Accept()
                //在死循环中不断接受请求,成功就返回一个连接
		if err != nil {
			log.Printf("Accept failed %v", err)
			continue
		}
		go process(client) //使用go routine 处理连接(可轻松处理上万并发)
                //前面要加go关键字相当于子线程
	}
}

func process(conn net.Conn) {//用process处理链接
	defer conn.Close() //一旦这个process函数结束就关闭连接
	reader := bufio.NewReader(conn)//缓冲流,减少底层系统调用
	for {
		b, err := reader.ReadByte() //每次读一个字节
		if err != nil {
			break
		}
		_, err = conn.Write([]byte{b}) //把读入的进行写也即返回(一个字节一个字节读,底层可能合并成几次大的读取操作)
		if err != nil {
			break
		}
	}
}

为了方便测试,这里输入什么,服务器就会返回什么,类似为子进程(但开销小)