Go语言实战案例

102 阅读4分钟

1 猜数字游戏

1.1 生成随机数

package main  
  
import (  
"fmt"  
"math/rand"  
)  
  
func main() {  
maxNum := 100  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
fmt.Println("The secret number is ", secretNumber)  
  
}

1.2 初始化随机数种子

package main  
  
import (  
"fmt"  
"math/rand"  
"time"//**新加行   
)  
  
func main() {  
maxNum := 1  
rand.Seed(time.Now().UnixNano()) //**用时间戳来初始化随机化种子  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
fmt.Println("The secret number is ", secretNumber)  
  
}

UnixNano()定义:func (t Time) UnixNano() int64

1.3 玩家输入

package main  
  
import (  
"bufio"//**  
"fmt"  
"math/rand"  
//**  
"os"  
"strconv"  
"strings"  
//**  
"time"  
)  
  
func main() {  
maxNum := 1  
rand.Seed(time.Now().UnixNano()) //用时间戳来初始化随机化种子  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
fmt.Println("The secret number is ", secretNumber)  
//**  
fmt.Println("Please input your guess")  
reader := bufio.NewReader(os.Stdin) //从终端读入  
input, err := reader.ReadString('\n') //读取一行  
if err != nil {  
fmt.Println("An error occured while reding input.Please try again", err)  
return  
}  
input := strings.TrimSuffix(input, "\n") //减去后缀  
guess, err := strconv.Atoi(input) //strconv包中的Atoi()函数将纯数字字符串转换为int类型返回  
if err != nil {  
fmt.Println("Invalid input.Please evter an integer value")  
return  
}  
fmt.Println("You guess is",guess)  
//**  
  
}

reader := bufio.NewReader(os.Stdin)功能:从终端读取数据生成*Reader os.Stdin:var Stdin *File = NewFile(uintptr(syscall.Stdin), "/dev/stdin")

NewFile()创建/dev/stdin新文件并将终端输入数据写入,返回*File类型,所以Stdinos库下的标准输入句柄

strings.TrimSuffix(str string,suffix)将str字符串的后缀suffix删除

strconv.Atoi(str string)str(纯数字字符串)转换为int类型并返回

1.4 实现逻辑判断

package main  
  
import (  
"bufio"  
"fmt"  
"math/rand"  
"os"  
"strconv"  
"strings"  
"time"  
)  
  
func main() {  
maxNum := 1  
rand.Seed(time.Now().UnixNano()) //用时间戳来初始化随机化种子  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
fmt.Println("The secret number is ", secretNumber)  
  
fmt.Println("Please input your guess")  
reader := bufio.NewReader(os.Stdin) //从终端读入  
input, err := reader.ReadString('\n') //读取一行  
if err != nil {  
fmt.Println("An error occured while reding input.Please try again", err)  
return  
}  
input := strings.TrimSuffix(input, "\n") //减去后缀  
guess, err := strconv.Atoi(input) //strconv包中的Atoi()函数将纯数字字符串转换为int类型返回  
if err != nil {  
fmt.Println("Invalid input.Please evter an integer value")  
return  
}  
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!")  
}  
//**
  
}

1.5 实现游戏循环

package main  
  
import (  
"bufio"  
"fmt"  
"math/rand"  
"os"  
"strconv"  
"strings"  
"time"  
)  
  
func main() {  
maxNum := 1  
rand.Seed(time.Now().UnixNano()) //用时间戳来初始化随机化种子  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
//fmt.Println("The secret number is ", secretNumber)  
  
fmt.Println("Please input your guess")  
reader := bufio.NewReader(os.Stdin) //从终端读入  
for {//**  
input, err := reader.ReadString('\n') //读取一行  
if err != nil {  
fmt.Println("An error occured while reding input.Please try again", err)  
//return  
continue//**  
}  
input := strings.TrimSuffix(input, "\r\n") //减去后缀  
guess, err := strconv.Atoi(input) //strconv包中的Atoi()函数将纯数字字符串转换为int类型返回  
if err != nil {  
fmt.Println("Invalid input.Please evter an integer value")  
//return  
continue//**  
}  
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//**  
}  
}//**  
}

1.6 最终代码实现

package main  
  
import (  
"bufio"  
"fmt"  
"math/rand"  
"os"  
"strconv"  
"strings"  
"time"  
)  
  
func main() {  
maxNum := 100  
rand.Seed(time.Now().UnixNano()) //用时间戳来初始化随机化种子  
secretNumber := rand.Intn(maxNum) //随机数函数rand.Intn(number int)//生成一个不超过number的非负整数  
fmt.Println("Please input your guess")  
reader := bufio.NewReader(os.Stdin) //从终端读入  
for {  
input, err := reader.ReadString('\n') //读取一行  
if err != nil {  
fmt.Println("An error occured while reding input.Please try again", err)  
continue  
}  
input = strings.TrimSuffix(input, "\r\n") //删除字符串中的\t\r\n  
guess, err := strconv.Atoi(input) //strconv包中的Atoi()函数将纯数字字符串转换为int类型返回  
if err != nil {  
fmt.Println("Invalid input.Please enter an integer value.err:", err)  
continue  
}  
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  
}  
}  
}

2 在线词典

因为这个项目涉及许多我不了解的知识,所以我只能跟着视频敲代码,下面是可运行代码:

package main  
  
import (  
"bytes"  
"encoding/json"  
"fmt"  
"io"  
"log"  
"net/http"  
"os"  
//"strings"  
)  
  
type DictRequest struct {  
TransType string `json:"trans_type"`  
Source string `json:"source"`  
UserID string `json:"user_id"`  
}  
  
type DiciResponse struct {  
Rc int `json:"rc"`  
Wiki struct {  
} `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) {  
client := &http.Client{}  
//var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)  
request := DictRequest{TransType: "en2zh", Source: word}  
buf, err := json.Marshal(request) //序列化,返回[]byte  
if err != nil {  
log.Fatal(err)  
}  
var data = bytes.NewReader(buf)  
//创建请求头  
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("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="8"`)  
req.Header.Set("sec-ch-ua-mobile", "?0")  
req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.5162 SLBChan/11")  
req.Header.Set("app-name", "xy")  
req.Header.Set("content-type", "application/json;charset=UTF-8")  
req.Header.Set("accept", "application/json, text/plain, */*")  
req.Header.Set("device-id", "dd0afa32b571973a3e17558bb28dc3a3")  
req.Header.Set("os-type", "web")  
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")  
req.Header.Set("origin", "https://fanyi.caiyunapp.com")  
req.Header.Set("sec-fetch-site", "cross-site")  
req.Header.Set("sec-fetch-mode", "cors")  
req.Header.Set("sec-fetch-dest", "empty")  
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")  
req.Header.Set("accept-language", "zh-CN,zh;q=0.9")  
resp, err := client.Do(req) //发起请求  
if err != nil {  
log.Fatal(err)  
}  
defer resp.Body.Close() //手动关闭流  
bodyText, err := io.ReadAll(resp.Body) //读取相应,返回的是[]byte数组  
if err != nil {  
log.Fatal(err)  
}  
if resp.StatusCode != 200 {  
log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))  
}  
//fmt.Printf("%s\n", bodyText) //打印json字符串  
var dictResponse DiciResponse  
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)  
}  
}  
func main() {  
if len(os.Args) != 2 {  
fmt.Fprint(os.Stderr, `usage: simpleDict WORD example: simpleDict hello`)  
os.Exit(1)  
}  
word := os.Args[1]  
query(word)  
}

3 SOCKS5代理介绍

代码示例:

package main  
  
import (  
"bufio"  
"context"  
"encoding/binary"  
"errors"  
"fmt"  
"io"  
"log"  
"net"  
)  
  
const (  
socks5Ver = 0x05  
cmdBind = 0x01  
atypIPV4 = 0x01  
atypeHOST = 0x03  
atypeIPV6 = 0x04  
)  
  
func main() {  
sever, err := net.Listen("tcp", "127.0.0.1:1080") //征信一个端口  
if err != nil {  
panic(err)  
}  
for {  
client, err := sever.Accept() //接受一个请求,返回连接  
if err != nil {  
log.Printf("Accept failed %v", err)  
continue  
}  
go process(client) //启动一个协程  
}  
}  
func process(conn net.Conn) {  
defer conn.Close()  
reader := bufio.NewReader(conn) //只读的带缓冲的流  
err := auth(reader, conn)  
if err != nil {  
log.Printf("client %v auth failed:%v", conn.RemoteAddr(), err)  
return  
}  
//log.Println("auth success")  
err = connect(reader, conn)  
if err != nil {  
log.Printf("client %v auth failed:%v", conn.RemoteAddr(), err)  
return  
}  
}  
func auth(reader *bufio.Reader, conn net.Conn) (err error) {  
ver, err := reader.ReadByte()  
if err != nil {  
return fmt.Errorf("read ver failed:%w", ver)  
}  
if ver != socks5Ver {  
return fmt.Errorf("not srpported ver:%v", ver)  
}  
methodSize, err := reader.ReadByte()  
if err != nil {  
return fmt.Errorf("read methodSize failed:%w", err)  
}  
method := make([]byte, methodSize)  
_, err = io.ReadFull(reader, method)  
if err != nil {  
return fmt.Errorf("read method failed:%w", err)  
}  
log.Println("ver", ver, "method", method)  
_, err = conn.Write([]byte{socks5Ver, 0x00})  
if err != nil {  
return fmt.Errorf("write failed:%w", err)  
}  
return nil  
}  
func connect(reader *bufio.Reader, conn net.Conn) (err error) {  
buf := make([]byte, 4)  
_, err = io.ReadFull(reader, buf)  
if err != nil {  
return fmt.Errorf("read header failed:%w", err)  
}  
ver, cmd, atyp := buf[0], buf[1], buf[2]  
if ver != socks5Ver {  
return fmt.Errorf("not supported ver:%v", ver)  
}  
if cmd != cmdBind {  
return fmt.Errorf("not supported cmd:%v", ver)  
}  
addr := ""  
switch atyp {  
case atypIPV4:  
_, err = io.ReadFull(reader, buf)  
if err != nil {  
return fmt.Errorf("read atyp failed:%w", err)  
}  
addr = fmt.Sprintf("%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3])  
case atypeHOST:  
hostSize, err := reader.ReadByte()  
if err != nil {  
return fmt.Errorf("read hostSize failed:%w", err)  
}  
host := make([]byte, hostSize)  
_, err = io.ReadFull(reader, host)  
if err != nil {  
return fmt.Errorf("read host failed:%w", err)  
}  
addr = string(host)  
case atypeIPV6:  
return errors.New("IPV6: no supported yet")  
default:  
return errors.New("invalid atyp")  
}  
_, err = io.ReadFull(reader, buf[:2])  
if err != nil {  
return fmt.Errorf("read port failed:%w")  
}  
port := binary.BigEndian.Uint16(buf[:2])  
dest, err := net.Dial("tcp", fmt.Sprintf("%v:L%v", addr, port))  
if err != nil {  
return fmt.Errorf("dial dst failed:%w", err)  
}  
defer dest.Close()  
log.Println("dial", addr, port)  
_, err = conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})  
if err != nil {  
return fmt.Errorf("write failed: %w", err)  
}  
ctx, cancel := context.WithCancel(context.Background())  
defer cancel()  
go func() {  
_, _ = io.Copy(dest, reader)  
cancel()  
}()  
go func() {  
_, _ = io.Copy(conn, dest)  
cancel()  
}()  
<-ctx.Done()  
return nil  
}