优化一个已有的 Go 程序,提高其性能并减少资源占用 | 青训营

79 阅读3分钟

猜谜游戏的优化

在上期,我们用Go语言构建了一个猜谜游戏,在这个游戏当中,程序首先会生成一个介于1到100之间的随机整数,然后提示玩家进行猜测。玩家每次输入一个数字,然后提示玩家进行猜测。玩家每次输入一个数字,程序会告诉玩家这个猜测的值是高于还是低于这个秘密的随机数,并且让玩家继续猜测。直到猜对为止,就会告诉玩家胜利并且退出程序。但是,一个小小的猜谜游戏的代码便已经高达44行,其性能也不高,占用资源较多,现在,让我们来试看看能不能优化代码,提高其性能并减少资源占用。

以下是上期的完整代码

为了生成随机数,我们需要用到math/rand包。首先我们要导入fmt包和math/rand包,定义一个变量,maxNum是你定义的最大值,我们用time.Now().UnixNano()来初始化随机种子。接下来是实现用户输入输出,并解析成数字,我们会用 bufio.NewReader 把一个文件转换成一个 reader 变量。现在我们有了一个秘密的值,然后也从用户的输入里面读到了一个值,我们来比较这两个值的大小。如果是用户输入的值比那个秘密的值要大的话,就告诉用户你猜的值太大了,请再试一次。如果是小了也同理,如果是相等的话,那么我们就告诉用户赢了。此时我们的程序大致可以正常工作了,但是玩家只能输入一次猜测,无论猜测是否正确,程序都会退出。为了让游戏可以正常玩下去,我们需要加一个循环。 具体实践过程和思路请看上一期

package main  
   
import (  
"bufio"  
"fmt"  
"math/rand"  
"os"  
"strconv"  
"strings"  
"time"  
)  
   
func main() {  
maxNum := 100  
rand.Seed(time.Now().UnixNano())   
secretNumber := rand.Intn(maxNum)  

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 reading input. Please try again", err)  
continue  
}  
input = strings.TrimSuffix(input, "\n") 
   
guess, err := strconv.Atoi(input)   
if err != nil {  
fmt.Println(err) 
fmt.Println("Invalid input. Please enter an integer value")  
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  
}  
}
}

仔细观察代码不难发现,在生成随机数和实现判断逻辑阶段的代码基本上达到了最佳。所以,我们能优化的地方只有读取用户输入(第18行到第34)的阶段,在这个阶段中我们用了 bufio.NewReader 把一个文件转换成一个 reader 变量,reader 变量上会有很多用来操作一个流的操作,我们用它的 ReadString 方法来读取一行。虽然这样的操作可行,但是也给系统带来了较大的资源浪费。现在,我们来试着简化这一部分的代码。

优化代码

通过观察和是思考后,我发现可以用fmt.Scanf来简化这一部分的代码,现在让我们来试试看。

package main  
   
import (  
"fmt"  
"math/rand"  
"time"  
)
...
fmt.Println("Please input your guess")  
for {  
var guess int  
_, err := fmt.Scanf("%d\n", &guess)  
if err != nil {  
fmt.Println("Invalid input. Please enter an integer value")  
continue  
}  
fmt.Println("You guess is", guess)
...

好了,现在代码已经优化完成,试试看能不能运行吧。通过实验后,我们发现代码还是可以完美的运行,并且代码从原来的44行减少到33行。不仅如此,还大大提高了程序的性能,减少了资源的占用,是一次成功的优化。