猜数字
- 猜数字
这个项目非常简单,它涉及到随机数的生成和用户输入操作。
我们使用了bufio库来处理输入数据。
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
简单字典
- 标准库strconv
它主要用于字符和其他类型之间的转换。
strconv.Atoi(s string) int
- 标准库strings
strings.TrimSuffix(s string , suffix string) string
删除末尾字符,如果没有就正常返回
- 网络库
client := &http.Client{}
初始化请求客户端
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
构造头
req.Header.Set("authority", "api.interpreter.caiyunai.com")
请求
bodyText, err := io.ReadAll(resp.Body)
err = json.Unmarshal(bodyText, &dictResponse)
- os库
word := os.Args[1]
获取环境参数
socks5代理
package main
import (
"context"
"encoding/binary"
"fmt"
"io"
"net"
)
const (
socks5Ver = 0x05
atypeIPV4 = 0x01
atypeHOST = 0x03
cmdConnect = 0x01
)
func main() {
// 假设在这里建立一个 net.Listener 监听 Socks5 代理请求
for {
client, err := acceptConnection()
if err != nil {
continue
}
// 开启一个 goroutine 处理客户端请求
go handleSocks5Client(client)
}
}
func acceptConnection() (net.Conn, error) {
// 实现接收连接请求的逻辑
}
func handleSocks5Client(conn net.Conn) {
defer conn.Close()
// 鉴权阶段
if err := auth(conn); err != nil {
fmt.Println("Authentication error:", err)
return
}
// 通讯阶段
addr, err := connect(conn)
if err != nil {
fmt.Println("Connection error:", err)
return
}
// 给客户端回包,表示连接成功
_, _ = conn.Write([]byte{socks5Ver, 0x00, 0x00, atypeIPV4, 0, 0, 0, 0, 0, 0})
// 开始进行数据转发
dest, err := net.Dial("tcp", addr)
if err != nil {
fmt.Println("Failed to connect to destination:", err)
return
}
defer dest.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 从客户端到目标地址的数据拷贝
go func() {
_, _ = io.Copy(dest, conn)
cancel()
}()
// 从目标地址到客户端的数据拷贝
go func() {
_, _ = io.Copy(conn, dest)
cancel()
}()
<-ctx.Done()
}
func auth(conn net.Conn) error {
buf := make([]byte, 2)
_, err := io.ReadFull(conn, buf)
if err != nil {
return err
}
ver, nmethods := buf[0], buf[1]
methods := make([]byte, nmethods)
_, err = io.ReadFull(conn, methods)
if err != nil {
return err
}
// 在这里根据收到的 methods 进行认证处理
// 假设这里选择不需要认证,回包告知客户端不需要认证
_, err = conn.Write([]byte{socks5Ver, 0x00})
if err != nil {
return err
}
return nil
}
func connect(conn net.Conn) (string, error) {
buf := make([]byte, 4)
_, err := io.ReadFull(conn, buf)
if err != nil {
return "", err
}
ver, cmd, _, atyp := buf[0], buf[1], buf[2], buf[3]
if ver != socks5Ver || cmd != cmdConnect {
return "", fmt.Errorf("Unsupported SOCKS5 command")
}
var addr string
switch atyp {
case atypeIPV4:
buf := make([]byte, 4)
_, err := io.ReadFull(conn, buf)
if err != nil {
return "", err
}
addr = fmt.Sprintf("%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3])
case atypeHOST:
hostSizeBuf := make([]byte, 1)
_, err := io.ReadFull(conn, hostSizeBuf)
if err != nil {
return "", err
}
hostSize := int(hostSizeBuf[0])
hostBuf := make([]byte, hostSize)
_, err = io.ReadFull(conn, hostBuf)
if err != nil {
return "", err
}
addr = string(hostBuf)
}
portBuf := make([]byte, 2)
_, err = io.ReadFull(conn, portBuf)
if err != nil {
return "", err
}
port := binary.BigEndian.Uint16(portBuf)
return fmt.Sprintf("%v:%v", addr, port), nil
}
使用 SOCKS5 代理的实现,涵盖了以下主要步骤:
鉴权阶段:
解析客户端发送的版本号、支持的认证方法数量和认证方法列表。
针对支持的认证方法进行验证,返回认证成功的回包。
通讯阶段:
解析客户端发送的连接请求,包括版本号、命令类型、目标地址类型、目标地址、目标端口等信息。
根据目标地址类型和地址解析方式,获取目标地址和端口号。
向目标地址发起连接请求,并返回连接成功的回包。
进程管理:
使用 goroutine 后台开启两个服务器交互进程。
通过 context 库进行进程管理,确保进程在必要时可以被关闭。
将客户端和目标之间的数据互相拷贝,使得数据能够在两者之间传递。
四、课后个人总结:
在这节课学习的内容中,我收获了很多关于Go语言编程的知识和技能。以下是我的感想:
Go语言的简洁和高效:通过学习这些基础标准库和相关功能,我深刻感受到Go语言的简洁和高效。标准库提供了丰富的功能,让编程变得更加简单和高效。
数据类型转换和字符串处理:学习了strconv和strings包,对于数据类型转换和字符串处理有了更深入的了解。这些工具使得在处理用户输入和数据转换时更加方便。
网络编程和HTTP库:了解了Go语言中的网络编程和net/http包,我现在能够编写简单的HTTP服务器和客户端,这对于开发网络应用和服务端程序非常有用。
文件操作和系统交互:通过os包的学习,我学会了如何在Go语言中进行文件操作和与操作系统进行交互,这对于处理文件和系统配置十分重要。
代理和鉴权:学习了socks5代理和鉴权机制,我对网络代理和安全认证有了更深刻的理解,这对于开发安全性较高的应用非常重要。
上下文处理:context包的学习使我了解了在Go语言中如何优雅地处理请求上下文,更好地控制请求的流程和生命周期。