并发请求与调用引擎|青训营

68 阅读3分钟

使用 fmt.Scanf 简化代码实现

fmt 标准库中,有三个函数用于扫描输入,分别是 ScanfScanScanln。它们之间存在一些区别:

  1. Scanf:可以识别换行符,需要传入格式化的字符串参数。
  2. Scan:可以识别换行符,不需要传入格式化的字符串参数。
  3. Scanln:不识别换行符,不需要传入格式化的字符串参数。

这些区别可能会在使用过程中导致问题:

  1. 在Windows系统中,换行符为 "\r\n"。如果未正确处理换行符,可能导致输入类型与指定类型不匹配,从而得到默认类型的值。
  2. 当读取的是数字字符时,如果输入的字符长度大于数字长度(例如汉字),但未读取到换行符,会影响后续的输入。

解决这些问题的方法如下:

  • 如果使用 fmt.Scanf,需要确保使用 "%d\r\n" 来处理换行符。或者,可以直接使用 fmt.Scan 来简化处理。
  • 针对错误输入,当出现错误时,需要读取当前行剩余的所有字符,然后跳到下一行继续处理。

核心代码示例:

var guess int
var err error
var buf string
for {
	_, err = fmt.Scan(&guess) 
	if err != nil {
		fmt.Println("读取输入时出错,请重试")
		fmt.Scan(&buf) // 读取当前行剩余的所有字符
		continue
	}
	// 后续处理逻辑,例如大小比较
}

新增另一种字典翻译引擎

考虑到许多翻译引擎的接口可能需要爬虫技术或者官方API调用,以下以百度翻译为例:

请求体结构如下:

var url = "https://fanyi-api.baidu.com/api/trans/vip/translate"
sign := fmt.Sprintf("%x", md5.Sum([]byte(appid+word+salt+key)))
res, err := http.PostForm(url,
	url.Values{
		"q":     {word},
		"from":  {"en"},
		"to":    {"zh"},
		"appid": {appid},
		"salt":  {salt},
		"sign":  {sign},
	})
if err != nil {
	log.Fatal(err)
}

解析响应的代码如下:

type Response struct {
	From        string `json:"from"`
	To          string `json:"to"`
	TransResult []struct {
		Src string `json:"src"`
		Dst string `json:"dst"`
	} `json:"trans_result"`
}

content, err := ioutil.ReadAll(res.Body)
if err != nil {
	log.Fatal(err)
}

var response Response
err = json.Unmarshal(content, &response)
if err != nil {
	log.Fatal(err)
}

fmt.Println(word, "翻译结果:", response.TransResult[0].Dst)

并发请求两个翻译引擎 可以使用多协程和锁来并发请求两个翻译引擎,可以通过打印时间戳来对照不同引擎的翻译效率:

var wg sync.WaitGroup
var mu sync.Mutex

wg.Add(2)
go func() {
	defer wg.Done()
	BaiduQuery(word)
	mu.Lock()
	defer mu.Unlock()
	fmt.Println("百度翻译在", time.Now(), "完成")
}()
go func() {
	defer wg.Done()
	CaiYunQuery(word)
	mu.Lock()
	defer mu.Unlock()
	fmt.Println("彩云翻译在", time.Now(), "完成")
}()
wg.Wait()

请注意,上述代码示例中的 BaiduQuery 和 CaiYunQuery 是代表两个不同翻译引擎的函数。这样,你可以在两个函数内部实现各自的翻译逻辑。同时,通过使用锁,可以确保在并发情况下,时间戳的打印不会交叉。

新增另一种字典翻译引擎 考虑到许多翻译引擎的接口可能需要爬虫技术或者官方API调用,以下以百度翻译为例:

请求体结构如下:

var url = "https://fanyi-api.baidu.com/api/trans/vip/translate"
sign := fmt.Sprintf("%x", md5.Sum([]byte(appid+word+salt+key)))
res, err := http.PostForm(url,
	url.Values{
		"q":     {word},
		"from":  {"en"},
		"to":    {"zh"},
		"appid": {appid},
		"salt":  {salt},
		"sign":  {sign},
	})
if err != nil {
	log.Fatal(err)
}

解析响应的代码如下:


type Response struct {
	From        string `json:"from"`
	To          string `json:"to"`
	TransResult []struct {
		Src string `json:"src"`
		Dst string `json:"dst"`
	} `json:"trans_result"`
}

content, err := ioutil.ReadAll(res.Body)
if err != nil {
	log.Fatal(err)
}

var response Response
err = json.Unmarshal(content, &response)
if err != nil {
	log.Fatal(err)
}
fmt.Println(word, "翻译结果:", response.TransResult[0].Dst)

并发请求两个翻译引擎

可以使用多协程和锁来并发请求两个翻译引擎,可以通过打印时间戳来对照不同引擎的翻译效率:

var wg sync.WaitGroup
var mu sync.Mutex

wg.Add(2)
go func() {
	defer wg.Done()
	BaiduQuery(word)
	mu.Lock()
	defer mu.Unlock()
	fmt.Println("百度翻译在", time.Now(), "完成")
}()
go func() {
	defer wg.Done()
	CaiYunQuery(word)
	mu.Lock()
	defer mu.Unlock()
	fmt.Println("彩云翻译在", time.Now(), "完成")
}()
wg.Wait()

请注意,上述代码示例中的 BaiduQuery 和 CaiYunQuery 是代表两个不同翻译引擎的函数。这样,你可以在两个函数内部实现各自的翻译逻辑。同时,通过使用锁,可以确保在并发情况下,时间戳的打印不会交叉。