文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

这是Go编程介绍的第二部分。 要快速启动和运行,从第一部分开始。

第一部分中,我们安装了Go并将我们程序放入到基本shell中。 在这第二篇文章中,我们将更新我们的程序以接受用户输入。 为此,我们首先需要了解变量。

变量作为容器

编程中的变量很像代数中的变量 - 它是某些值的占位符。 更准确地说,一个变量是一个容器,一个可以是空的或可能包含一些东西的盒子。 编程中的变量也有“类型”,也就是说,如果变量保存一个整数,我们说它的类型是“integer”。 Go中的每个变量都被赋予一个类型,并且只允许保存该类型的值,所以在我们进一步之前,我们需要知道什么类型是可用的。

第 1 段(可获 1.93 积分)

基本(标量)类型

最基本的类型被称为“标量”类型,这意味着它只是其中的一个。 如果我们的盒子只有一个项目,它是一个标量盒。 Go有几种标量类型,包括:* int,包含整数;* float32和float64,包含浮点十进制数;* bool,包含true或false; * string,包含放在一起的字符,即文本。

在第3部分中,我们将使用包含多个值的变量,但是标量类型现在已经足够了。

声明和赋值

那么如何设置变量的类型,以及如何将值放入变量盒子中呢? 这两个操作称为“声明”和“赋值”。 在Go中,使用var关键字后跟一个名称和类型声明一个变量:

第 2 段(可获 1.53 积分)
var someVariable int

然后,使用=运算符来赋值(即,在盒子中放入一些内容)

someVariable = 5
fmt.Println(someVariable)
// output: 5

声明和分配也可以同时进行:

var someVariable int = 5

现在我们可以将someVariable传递给函数,如fmt.Println(),随意分配新值,甚至将其值赋给其他变量。

重要点:变量只声明一次,但可以赋值任意次数。 变量必须在使用前声明。

相同的语法也用于其他类型,但是对于字符串,您需要将值括在引号中:

第 3 段(可获 1.1 积分)
var someString string = "This is some text"

指针

基于我们的类比,变量的“盒子”实际的是你的计算机RAM的一小块。 变量的类型决定了盒子有多大(要使用多少RAM)以及它允许的内容。

一种特殊类型的变量称为“指针”。 指针也是一小块RAM,但它不是具有自己的值,而是保存另一个变量的内存地址。 在Go中,通过在要指向的变量的名称之前放置一个符号来分配指针。 比较以下声明和赋值:

第 4 段(可获 1.28 积分)
var aCopyOfSomeVariable int = someVariable
var pointsToSomeVariable *int = &someVariable

第一个将someVariable的值赋给aCopyOfSomeVariable。 它复制的变量值,对一个变量的更改不会影响另一个。 第二个创建一个指向someVariable的指针。 使用pointsToSomeVariable,你实际上可以修改someVariable的内容。

注意我们的指针的类型:* int意味着它指向一个int。 它说,“我自己不是一个int,但我可以告诉你在哪里找到一个。

指针的主题是复杂的,我现在不会拿太多细节麻烦你。 你需要知道的是,你可以让一个函数修改你的变量——给它一个指针,我们就能实现。

第 5 段(可获 1.41 积分)

接受参数

我们的程序需要知道三件事:1.包含我们GIF帧的文件夹,2.每帧之间设置多少延迟,3.输出文件的命名。

在我们的main()函数上面,我们声明了名为“path”,“delay”和“output”的三个变量。

var path, output string
var delay int

func main() {
// ...

正如你所看到的,同一类型的变量(在这种情况下是字符串)可以一起声明,所以你不必多次写入类型。

现在我们如何得到这些变量的值? 我们可以硬编码inmain()中的值,像这样:

第 6 段(可获 1.14 积分)
func main() {
    path = "./some_folder/"
    output = "output.gif"
    delay = 5
}

但这样做并不好,因为我们经常需要改变它们。 我们需要一种方法来获得用户的输入。

flag包

让我们使用命令行 flags 来接受用户的参数。 开始前,在文件的顶部从标准库导入flag包。

import (
    "flag"
    "fmt"
)

flag包有很多功能,你可以阅读golang.org/pkg/flag/上的文档。 我们将使用StringVar()和IntVar()。 这些函数会完成解析用户输入,将其转换为所需的类型,并将其放入我们指定的变量的所有的工作。 我们将从设置路径开始。

第 7 段(可获 1.29 积分)
func main() {
    flag.StringVar(&path, "p", "", "path to the folder containing images")
}

StringVar() 的参数是:1.指向字符串变量的指针。 这里我们通过写&path指向路径。 2.命令行标志。 我们输入了“p”,这意味着用户将键入go-gif-generator -p / the / folder。 3.默认值。 我们将要求输入一个路径(稍后更多),因此我们提供一个空字符串作为默认值。 4.参数的描述。 这用于为用户自动生成帮助消息。

让我们设置输出和延迟,默认为“output.gif”和5秒。 当我们完成设置参数时,我们调用flag.Parse()来解析用户输入。

第 8 段(可获 1.28 积分)
func main() {
    flag.StringVar(&path, "p", "", "path to the folder containing images")
    flag.StringVar(&output, "o", "output.gif", "the name of the generated GIF")
    flag.IntVar(&delay, "d", 5, "delay between frames in seconds")
    flag.Parse()
}

这就行了。 现在用户可以即时更改应用程序的行为。 把所有的片段放在一起,尝试编译。

验证用户输入

我们提到需要一个路径参数,但到目前为止,我们没有采取任何措施来执行。 虽然我们在这里,让我们也确保延迟是合理的。 我们需要写一个条件语句:如果path是空的,告诉用户它是必需的,然后退出。

第 9 段(可获 0.91 积分)

Go有常用的比较运算符:==,!=,<,<=,>,> =。 这些就像你在数学中使用的符号,使用你的键盘当作字符输入也很容易。 我们将使用一个简单的==来检查路径是否等于空字符串,即“”。

注意,相等的比较运算符是==,而不是=。 单个等号已经用于赋值。

在Go中的条件被写为如果后面跟随一个或多个条件。 你把当条件评估为true时运行的任何代码放入内部花括号。 在我们的例子中,这样写:

if path == "" {
   fmt.Println("A path is required")
   flag.PrintDefaults()
   return
}
第 10 段(可获 1.16 积分)

很简单:首先,flag.PrintDefaults() - flag包中的一个函数 - 将打印我们上面定义的参数及其描述。 然后,因为没有路径参数我们不能继续,我们使用return来停止我们的函数,从而退出我们的程序。

函数和返回值

函数最后一件事情是“返回”一个值到任何调用它的代码。 当返回发生时,函数退出并且不执行该行之后的任何代码。 例如,如果我键入return 1,我的函数会停在它的位置,并将数字1传回给调用者。

第 11 段(可获 1.18 积分)

一些函数,像我们的函数main(),不返回任何东西。 在这种情况下,我们允许使用一个单独的return来表示函数执行应该停止。

Go 给我们布尔运算符&&(和)和 || (或),这样我们可以把多个条件放在一个if中。 为了检查延迟,我们将使用 ||。 此时,我们将不打印默认使用情况:

if delay < 1 || delay > 10 {
   fmt.Println("delay must be between 1 and 10 inclusively")
   return
}

在英语中,这意味着“如果延迟小于1或大于10,反馈给用户”。

美国的键盘| 字符是shift + \,在enter/return 键上方会找到它。

第 12 段(可获 1.14 积分)

把它放在一起

我们的代码这样应该看起来效果更好:

package main

import (
    "flag"
    "fmt"
)

var path, output string
var delay int

func main() {
    flag.StringVar(&path, "p", "", "path to the folder containing images")
    flag.StringVar(&output, "o", "output.gif", "the name of the generated GIF")
    flag.IntVar(&delay, "d", 5, "delay between frames in seconds")
    flag.Parse()

    if path == "" {
        fmt.Println("A path is required")
        flag.PrintDefaults()
        return
    }

    if delay < 1 || delay > 10 {
        fmt.Println("delay must be between 1 and 10 inclusively")
        return
    }

    fmt.Println("This will be a GIF generator!")
}

使用命令go install编译它,然后尝试不同的选项。 实践中,可以添加几个fmt.Println()调用来显示用户输入,或添加几个参数输入。 在下一课中,我们将对所有这些设置进行一些操作!

准备继续? 在第三部分中完成你的GIF生成器。

第 13 段(可获 0.85 积分)

文章评论