Go语言入门经典(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-28 03:26:19

点击下载

作者:(英)乔治 奥尔波(George Ornbo)

出版社:人民邮电出版社有限公司

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Go语言入门经典

Go语言入门经典试读:

前言

Go(Golang)语言是编程语言设计的又一次尝试,是对类C语言的重大改进。它让您能够访问底层操作系统,还提供了强大的网络编程和并发编程支持。

Go语言用途众多,其中包括如下几种。● 网络编程。● 系统编程。● 并发编程。● 分布式编程。

很多重要的开源项目都是使用Go语言开发的,其中包括Go-Ethereum、Terraform、Kubernetes和Docker。Go语言给开源界带来了重大影响,有望提高开源项目的成功率。本书读者对象

本书不要求读者具备任何编程或计算机方面的经验,但如果对编程有基本的认识将大有裨益。由于Go代码主要是从终端运行的,因此熟悉终端以及如何在其中执行基本命令是十分必要的。最后,鉴于Go语言常用于系统编程和网络编程,因此对互联网的工作原理有些了解也将很有帮助,虽然这并非必要的。为何要学习Go语言

如果您要创建系统程序或基于网络的程序,Go语言是很不错的选择。作为一种相对较新的语言,它是由经验丰富且受人尊敬的计算机科学家设计的,旨在应对创建大型并发网络程序面临的挑战。如果您觉得Java或C语言的语法导致编程很难,那么Go语言将可能提供更佳的体验。对具备诸如Ruby、Python、JavaScript等动态语言使用经验的程序员来说,Go语言提供了类型安全,同时又不像传统语言那么死板。组织结构

本书首先介绍Go语言基础知识,包括搭建Go语言编程环境以及运行第一个Go程序。接下来介绍一些重要的Go语言知识,包括字符串、函数、结构体和方法。您将学会如何使用Goroutine和通道,这些是Go语言特有的功能,它们避免了并发编程的大部分难题。

然后,您将学习如何调试和测试Go语言代码,并学会一些帮助编写独具Go语言风格代码的技巧。

接下来,您将学习如何编写基本的命令行程序、HTTP服务器和HTTP客户端,并学习如何处理JSON数据和文件。

最后,您将学习正则表达式相关的知识、如何处理时间以及如何将Go应用程序部署到生产环境中。代码示例

本书每章都有多个代码示例,旨在帮助您学习Go语言,它们与正文一样重要,强烈建议您在阅读过程中运行这些示例代码。本书的示例代码可在异步社区本书页面中下载。资源与支持

本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。配套资源

本书提供如下资源:

本书配套资源请到异步社区的本书购买页面中下载。

要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。提交勘误

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。扫码关注本书

扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。与我们联系

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/ selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。关于异步社区和异步图书“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。异步社区微信服务号第1章 起步

本章介绍如下内容。● Go简介。● 安装Go。● 设置环境。● 编写您的第一个Go程序——Hello World。

通过阅读本章,您将知道Go是什么以及创建它的动机是什么。您将学习如何安装Go并运行第一个程序。您还将了解Go Gopher,它会在本书中时不时地蹦出来。1.1 Go简介

Go(或Golang)是Google在2007年开发的一种开源编程语言,出自Robert Griesemer、Rob Pike和Ken Thompson之手。2009年11月10日,Google Open Source Blog向全球发布了这款语言;公告指出Go的主要目标是“兼具Python等动态语句的开发速度和C或C++等编译型语言的性能与安全性”。1.1.1 Go语言简史

对语言进行评估时,明白设计者的动机以及语言要解决的问题很重要。Go语言的设计者都是计算机科学领域的重量级人物。在20世纪70年代,Ken Thompson设计并实现了最初的UNIX操作系统,仅从这一点说,他对计算机科学的贡献怎么强调都不过分。他还与Rob Pike合作设计了UTF-8编码方案。除帮助设计UTF-8外,Rob Pike还帮助开发了分布式多用户操作系统Plan 9,并与人合著了The Unix Programming Environment,对UNIX的设计理念做了正统的阐述。Robert Griesemer就职于Google,对语言设计有深入的认识,并负责Chrome浏览器和Node.js使用的Google V8 JavaScript引擎的代码生成部分。

这些计算机科学领域的重量级人物设计Go语言的初衷是满足Google的需求。设计此语言花费了两年的时间,融入了整个团队多年的经验及对编程语言设计的深入认识。设计团队借鉴了Pascal、Oberon和C语言的设计智慧,同时让Go语言具备动态语言的便利性。因此,Go语言体现了经验丰富的计算机科学家的语言设计理念,是为全球最大的互联网公司之一设计的。Go语言的所有设计者都说,设计Go语言是因为C++给他们带来了挫败感。在Google I/O 2012的Go设计小组见面会上,Rob Pike是这样说的:“我们做了大量的C++开发,厌烦了等待编译完成,尽管这是玩笑,但在很大程度上来说也是事实。”

您无须知道Go语言的设计历史就能使用它。您只需知道,Go语言的设计和实现体现了多位计算机专家多年的经验以及对其他编程语言优缺点的深入认识。因C++的不良体验而出现的Go语言是一门现代编程语言,可用来创建性能卓越的Web服务器和系统程序。1.1.2 Go是编译型语言

Go使用编译器来编译代码。编译器将源代码编译成二进制(或字节码)格式;在编译代码时,编译器检查错误、优化性能并输出可在不同平台上运行的二进制文件。要创建并运行Go程序,程序员必须执行如下步骤。

1.使用文本编辑器创建Go程序。

2.保存文件。

3.编译程序。

4.运行编译得到的可执行文件。

这不同于Python、Ruby和JavaScript等语言,它们不包含编译步骤。有关使用编译器的优缺点,将在第2章介绍。Go自带了编译器,因此无须单独安装编译器。1.2 安装Go

Go可用于FreeBSD、Linux、Windows和macOS等操作系统。如果您使用的是这些操作系统的较新版本,它们很可能支持Go。有关对这些平台的要求,请参阅Go网站列出的系统需求。推荐尽可能使用操作系统自带的包管理器来安装Go。

开发者也可使用从Golang网站下载的文件来安装Go。如果您是新手,推荐使用安装程序来安装,尽管没有用于Linux系统的Go安装程序,但通常可使用包管理器来安装;如果您是经验丰富的Linux用户,可使用源代码来安装Go,如果您使用的是Windows或macOS系统,只需下载相应的文件并双击它,再按说明完成安装过程即可。您将看到一个标准的安装程序窗口,如图1.1所示。图1.1 在Windows系统中运行Go安装程序1.2.1 在Windows系统中安装

安装程序运行完毕后,打开命令提示符并执行命令go version。如果您看到包含版本号的输出(如图1.2所示),就说明正确地安装了Go。图1.2 在Windows系统中核实正确地安装了Go

要完成安装,还需为Go项目创建目录结构。为此,使用“开始”菜单打开命令提示符,并创建如下目录(如图1.3所示)。mkdir %USERPROFILE%\gomkdir %USERPROFILE%\go\binmkdir %USERPROFILE%\go\pkgmkdir %USERPROFILE%\go\src图1.3 为Go项目创建目录结构

创建这些文件夹后,就可添加环境变量GOPATH了。在Windows系统中添加这个环境变量的步骤如下。

1.单击“开始”菜单中的“控制面板”。

2.搜索“环境变量”。

3.单击“编辑账户的环境变量”,打开如图1.4所示的对话框。

4.单击“New(新建)”按钮。

5.在Variable(变量名)文本框中输入GOPATH。

6.在Value(值)文本框中输入%USERPROFILE%\go。

7.单击“保存”按钮。图1.4 在Windows系统中设置环境变量GOPATH

如果您打开了命令提示符,将其关闭再重新打开。在提示符下执行如下命令,以检查是否设置了环境变量GOPATH:echo %GOPATH%C:\Users\george\go1.2.2 在macOS或Linux系统中安装

安装程序运行完毕后,打开命令提示符并执行命令go version。如果您看到包含版本号的输出(如图1.5所示),就说明正确地安装了Go。图1.5 在macOS系统中核实是否正确地安装了Go

要完成安装,还需要为Go项目创建目录结构。为此,打开终端并创建如下目录:mkdir $HOME/gomkdir $HOME/go/binmkdir $HOME/go/pkgmkdir $HOME/go/src

为设置环境变量GOPATH,请编辑.bashrc(如果您运行的是其他shell,请编辑相应的文件),在其中添加如下内容。.bashrc位于您的主(home)目录下。export GOPATH=$HOME/go

重新加载shell或关闭并重新打开终端。在提示符下执行如下命令,以检查是否设置了环境变量GOPATH:echo $GOPATH/home/george/go1.3 设置环境

Go根据您的环境配置行事。作为一个开源项目,代码分享也很重要。为在以后能够分享代码,推荐您创建一个Github账户。如果您没有这样的账户,则可前往Github网站免费创建;如果您要使用其他服务,如Gitlab或Bitbucket,则需要在后面的命令中将github.com替换为您要使用的服务的URL。如果您不熟悉Git和GitHub,也不用担心,本书后面会介绍。创建Github账户后,像下面这样创建用于存储源代码的文件夹:// Linux / macOSmkdir -p $GOPATH/src/github.com/[your github username]// Windowsmkdir %GOPATH%\src\github.com\[your github username]1.4 编写第一个Go程序——Hello World

现在该来编写著名的Hello World程序了!如果您已安装好Go,则只要有文本编辑器就可以创建Go程序了。如果您还没有喜欢的文本编辑器,可考虑使用Sublime、Textmate、Notepad++、Atom、Vim、Emacs等。至于哪款文本编辑器最好,程序员们就此争论得非常激烈,但如果您是新手,选择您用得顺手的编辑器就好。Go对文本编辑器没有特殊要求,因此如果您只是想尝试一下Go,使用操作系统提供的默认文本编辑器就可以了。

程序清单1.1列出了Go程序Hello World的代码。这个程序很简单,只是向终端打印一行文本。

程序清单1.1 Hello World 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   fmt.Println("Hello World!") 9: }TRY IT YOURSELF▼ 显示Hello World!在这个示例中,您将运行第一个Go程序!1.创建一个用于存储这个程序的文件夹,再切换到这个文件夹。// Linux / macOSmkdir -p $GOPATH/src/github.com/[your github username]/hellocd $GOPATH/src/github.com/[your github username]/hello// Windowsmkdir %GOPATH%\src\github.com\[your github username]\hellocd %GOPATH%\src\github.com\[your github username]\hello2.打开本书代码示例中的文件hour01/example01。3.在刚创建的文件夹hello中,创建一个名为main.go的文件。4.将文件hour01/example01的内容复制到main.go中。5.在文件夹hello中,执行命令go build。6.在文件夹中,执行命令run./main(Linux或macOS系统)或main.exe(Windows系统)。7.您将在控制台中看到Hello World!。8.祝贺您运行了第一个Go程序!▲

 提示:大多数语言都提供了Hello World示例。Hello World是一个简单的编程示例,用于展示编程语言的语法。它常用于检查安装是否正确以及简单地介绍语言。它还能够让您对不同的编程语言进行快速比较。1.4.1 使用go run编译并运行程序

编译并运行文件是开发过程中的一个常见步骤,Go提供了完成这个步骤的快捷途径。使用下面的命令编译并运行程序:go run main.go

不同于go build,go run不会创建可执行文件。在开发Go代码时,go run提供了一种便利的方式,因为没有必要将编译和执行步骤分开。另外,也不需要运行go clean来清除可执行文件。1.4.2 Go吉祥物

Go编程语言有一个吉祥物!在会议、文档页面和博文中,大多会包含如图1.6所示的Go Gopher,这是才华横溢的插画家Renee French设计的,她也是Go设计者之一Rob Pike的妻子。图1.6 Go吉祥物Gopher(由Renee French设计)1.5 小结

本章介绍了Go语言的设计者以及它们设计Go语言的动机。您安装了Go并运行了第一个程序;还了解了命令go build和go run的差别以及Go Gopher。在一章内学习了这么多内容真的很不错!1.6 问与答

问:既有的语言很多,为何还要设计Go语言?

答:设计Go语言是因为Java和C++ 等传统语言繁琐、缓慢而难以理解。Go语言的设计者借鉴了Python动态类型语言的优点,旨在打造一款易于使用并可用于开发高流量生产系统的语言。

问:编译器生成的可执行文件很大,但源代码文件很小。为何会这样?

答:在编译器生成的二进制文件中,必须包含执行程序所需的一切。这带来的缺点是二进制文件比源代码文件大,但优点是无须安装依赖就能运行程序。

问:该使用命令go build还是go run?

答:在开发阶段,推荐使用命令go run;程序开发完毕,可以分享时,建议使用go build。1.7 作业

作业包含小测验和答案,旨在加深对本章内容的理解。请尽可能先回答所有的问题再看后面的答案。1.7.1 小测验

1.要运行Go程序,都需要什么?

2.您能说出go build和go run的不同之处吗?

3.Go Gopher是什么?1.7.2 答案

1.除计算机外,您只需终端和文本编辑器。

2.命令go build执行编译,生成一个可执行的二进制文件,这个文件可用来运行程序;命令go run编译并运行程序。

3.Go Gopher是Go语言的吉祥物,其身影在整个Go生态系统中随处可见。1.8 练习

1.修改程序Hello World,让它显示您想说的其他文本。使用命令go build编译这个程序,再运行生成的可执行文件。再次修改要显示的文本,并使用命令go run运行这个程序。您现在明白这两个命令的差异了吗?

2.在网上搜索使用其他各种语言编写的Hello World程序。您能发现这些程序与本章的示例程序有什么相同之处吗?

3.如果有时间,请观看Rob Pike在2009年介绍Go编程语言的视频,其中概述了Golang的众多设计目标。第2章 理解类型

本章介绍如下内容。● 数据类型是什么?● 区分静态类型和动态类型。● 使用布尔类型。● 理解数值类型。● 检查变量的类型。● 类型转换。

Go是一种静态类型语言,而静态类型是一个必须理解的概念,如果您不是学计算机的,或者使用过Python、JavaScript等动态语言,这尤其重要。本章介绍数据类型,并帮助您理解强类型语言和动态类型语言的差别。您将学习Go语言类型系统的工作原理及其基本类型。2.1 数据类型是什么

数据类型让编程语言、编译器、数据库和代码执行环境知道如何操作和处理数据。例如,如果数据类型为数字,通常可对其执行数学运算。编程语言和数据库常常根据数据类型赋予程序不同的功能和性能。大多数编程语言还提供了用于处理常见数据的标准库,而数据库提供了查询语言,让程序员能够根据底层数据类型来查询数据以及与之交互。无论数据类型是否被显式地声明,它们都是重要的编程和计算结构。2.2 区分静态类型和动态类型

所谓强类型语言,指的是错误地使用了类型时,编译器将引发错误;所谓动态类型(也叫松散类型或弱类型)语言,指的是为了执行程序,运行时会将一种类型转换为另一种类型,或者编译器没有实现类型系统。哪种语言更好呢?这存在很大的争议,计算机科学家看重强类型语言的正确性和安全性,而其他人则看重动态语言的简单性和开发速度。

下面是静态类型语言的一些优点。● 性能高于动态类型语言。● Bug通常会被编译器发现。● 代码编辑器可提供代码补全和其他功能。● 数据完整性更好。

下面是动态类型语言的一些优点。● 使用动态类型语言编写软件的速度通常更快。● 无须为执行代码而等待编译器完成编译。● 动态类型语言通常不那么死板,因此有些人认为变更代码更容

易。● 有些人认为动态类型语言学习门槛更低。

在Go中,程序员可显式地声明类型,也可让编译器推断类型。在本章中,我们将显式地声明类型,以帮助您理解。程序清单2.1是一个向终端打印消息的程序。

程序清单2.1 类型简介 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func sayHello(s string) string { 8:   return "Hello " + s 9: }10:11: func main() {12:   fmt.Println(sayHello("George"))13: }

如果您不能完全理解程序清单2.1,也不用担心。这里的重点是函数sayHello的声明。从参数声明可知,这个函数接受一个类型为string的参数;这个函数的返回值也是字符串。因此,编译这个程序时,编译器将检查传递给这个函数的参数是否是字符串;如果不是,编译器将引发错误。这正是我们希望的,因为这意味着错误可能根本不会让用户遇到。

为了比较强类型语言和动态类型语言,下面来看一个JavaScript示例。JavaScript是一种使用广泛的动态类型语言,如果您不熟悉,也没关系。这里的重点是看看它在处理类型方面有何不同。

程序清单2.2是一个简单的JavaScript函数,它接受两个值,将它们相加并返回结果。

程序清单2.2 简单的JavaScript函数 1: var addition = function (a, b) { 2:   return x + y; 3: };

给这个函数提供两个数字时,它能够正确地运行。addition(1,3)4

然而,如果向它传递一个数字和一个字符串,结果将很怪异。addition(1,"three")1three

在这种情况下,这个函数返回一个字符串。怎么会这样呢?虽然JavaScript有类型的概念,但其类型使用规则非常宽松。在这个示例中,JavaScript对数字值执行类型转换,将其转换为字符串,因此返回字符串1three。JavaScript提供的这种灵活性虽然很有吸引力,但可能导致微妙乃至灾难性的Bug。

假设有个程序使用上述addition函数来接受输入并将其存储到数据库中。数据库通常有数据类型的概念,很多还有整数的概念。整数是没有小数部分的数字,可正可负。如果数据库将字段定义成了整型,就会要求提供给该字段的值为整数。

前述JavaScript函数addition可能返回一个字符串,也可能返回一个整数。如果传递给它的值至少有一个字符串,返回的就是字符串。如果这个返回值被插入到需要整数的数据库字段中,将引发错误。更糟糕的是,这种错误发生在运行阶段,这意味着它将影响使用程序的用户。这种错误除非得到妥善处理,否则可能导致程序崩溃。

而在使用Go语言编写的函数中,对参数和返回值的类型都做了声明。

程序清单2.3是一个使用Go语言编写的函数,这个函数指出它接受两个int值,并返回一个int值。即便不看这个函数的实现,也知道它接受两个整数并返回一个整数。如果程序员错误地将一个字符串传递给这个函数,编译器将捕获这种错误。

程序清单2.3 Go语言中的类型 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func addition(x int, y int) int { 8:   return x + y 9: }10:11: func main() {12:   fmt.Println(addition(2,4))13: }

在程序清单2.4所示的示例中,向函数传递了类型不正确的参数。在这个示例中,将在编译阶段发现这种错误,避免用户遭遇软件崩溃。

程序清单2.4 传递类型不正确的参数 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func addition(x int, y int) int { 8:   return x + y 9: }10:11: func main() {12:   var s string = "three"13:   fmt.Println(addition(1, s))14: }

如果您尝试运行这个程序,将出现编译错误。编译错误提供了有用的信息,让您知道出现错误的原因。在这里,原因是在需要int的地方使用了字符串。cannot use s (type string) as type int in argument to addition

Go编译器还能捕获其他常见的错误,如传递的参数太多或太少。TRY IT YOURSELF▼ 传递类型不正确的参数在这个示例中,您将明白Go编译器是如何实现类型系统的。1.打开本书代码示例中的hour02/example04.go。2.在终端执行命令go run example04.go来运行这个程序。3.您将看到如下错误消息。./example04.go:11: cannot use s (type string) as type int in argument to addition▲2.3 使用布尔类型

对类型有了基本认识后,就可探索Go是如何实现一些基本数据类型的了。首先来看布尔类型。布尔值只能为true或false。虽然有些语言允许使用值1和0来表示true和false,但Go语言不允许。可像下面这样声明布尔变量。var b bool

如果没有给布尔变量赋值,它将默认为false。程序清单2.5声明了一个布尔变量,再将其打印到终端。

程序清单2.5 声明布尔变量 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var b bool 9:   fmt.Println(b)10: }

布尔变量可在声明后重新赋值(参见程序清单2.6),它们是很有用的编程元素。

程序清单2.6 给布尔变量重新赋值 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var b bool 9:   fmt.Println(b)10:   b = true11:   fmt.Println(b)12: }TRY IT YOURSELF▼ 声明布尔变量并给它重新赋值在这个示例中,您将明白如何初始化布尔变量以及给它重新赋值。1.打开本书代码示例中的hour02/example06.go。2.在终端中执行命令go run example06.go以运行这个程序。3.您将看到给其中的布尔变量重新赋值了。  false  true▲2.4 理解数值类型

对编程来说,数值不可或缺。然而,如果您没有计算机科学或数学方面的知识,可能对有些术语感到迷惑。您可能听说过浮点数、整数、无符号整数、8位、64位、bigint、smallint、tinyint,这些都是整型(数值)类型。要明白这些术语的含义,必须知道数字在计算机内部是以二进制位的方式存储的。二进制位就是一系列布尔值,取值要么为1,要么为0。1位可表示1或0,对于4位整数,表2.1对其二进制表示和十进制表示做了比较。从该表可知,4位可表示16个不同的数字。表2.1 4位的无符号整数二进制十进制000000001100102001130100401015011060111710008100191010101011111100121101131110141111152.4.1 带符号整数和无符号整数

对于带符号整数,需要使用一位来表示符号,这通常是符号−。表2.1列出了无符号的4位整数,其取值范围为0~15。带符号整数可正可负,因此4位带符号整数的取值范围为−8到7,如表2.2所示。表2.2 4位的带符号整数二进制十进制00000000110010200113010040101501106011171000−81001−71010−61011−51100−41101−31110−21111−1

 提示:可使用的最大数值取决于计算机处理器。在计算机中,可使用的最大数值取决于计算机处理器的体系结构。当今的计算机大多是64位的,支持的最大无符号整数为9223372036854775807。第一代微处理器有些只有4位,这意味着只能表示−8~7的带符号整数!

在Go语言中,声明整型变量的方式如下。var i int = 3

类型int表示带符号整数,因此可正可负。根据计算机的底层体系结构,int可能是32位的带符号整数,也可能是64位的带符号整数。除非要处理的数字非常大,或者非常在乎性能,否则只需使用int,而无须关心编译器是如何做的。2.4.2 浮点数

浮点数是带小数点的数字,如11.2、0.1111、43.22。整数不能包含小数部分,因此要处理分数,必须使用浮点数。根据实际数字的大小,Go语言中的浮点数可以是32位的,也可以是64位的。在大多数现代计算机中,推荐使用float64。var f float32 = 0.1112.4.3 字符串

字符串可以是任何字符序列,其中的字符可能是数字、字母和符号。下面是一些简单的字符串。● cow。● $^%$。● a1234。

几乎所有的编程语言都支持字符串,它们通常包含数字、字母或符号。在Go语言中,声明并初始化字符串变量很简单。var s string = "foo"

字符串变量可以为空,这种变量非常适合用来累积其他变量中的数据以及存储临时数据。var s string = ""

创建字符串变量后,可将其与其他数据相加,但不能修改原来的值。下面的代码创建一个空字符串,再将字符串foo附加到末尾,这在Go语言中是合法的。var s string = ""s += "foo"

不能对字符串执行数学运算,即便它看起来像个数字。要想对看起来像数字的字符串执行数学运算,必须先将其转换为数字类型。2.4.4 数组

数组是几乎所有编程语言都支持的另一种数据类型,这是一种比较复杂的类型,因为它包含一系列元素。例如,要表示乐队的成员,使用字符串数组是不错的选择。声明数组时,必须指定其长度和类型。var beatles [4]string

在这个示例中,方括号内的数字表示数组的长度,而紧跟在方括号后的是数组的类型——这里为字符串。beatles[0] = "John"beatles[1] = "Paul"beatles[2] = "Ringo"beatles[3] = "George"

数组将在第6章详细介绍。注意:数组索引从0开始。您可能注意到了,在上述变量声明中,指定的数组长度为4,但访问这个数组的元素时,索引最大为3。这是因为在所有数组中,索引都从0开始。刚接触时,您可能对这一点感到迷惑。2.5 检查变量的类型

有些情况下,需要检查变量的类型,为此可使用标准库中的reflect包,它让您能够访问变量的底层类型。在大多数情况下,编译器都能发现类型不正确的情形,但在调试或必须核实底层类型时,reflect包将很有用,如程序清单2.7所示。

程序清单2.7 使用reflect包检查变量类型 1: package main 2: 3: import ( 4:   "fmt" 5:   "reflect" 5: ) 6: 7: func main() { 8:   var s string = "string" 9:   var i int = 1010:   var f float32 = 1.211:12:   fmt.Println(reflect.TypeOf(s))13:   fmt.Println(reflect.TypeOf(i))14:   fmt.Println(reflect.TypeOf(f))15: }TRY IT YOURSELF▼ 检查类型1.打开本书代码示例中的hour02/example07.go。2.在终端中执行命令go run example07.go以运行这个程序。3.控制台中将显示了变量的类型。  string  int  float322.6 类型转换

将数据从一种类型转换为另一种类型是常见的编程任务,这通常是在从网络或数据库读取数据时进行的。Go标准库提供了良好的类型转换支持。strconv包提供了一整套类型转换方法,可用于转换为字符串或将字符串转换为其他类型。

假设有一个字符串变量s,其值为“true”,要将其用于布尔比较,必须先转换为布尔类型。var s string = "true"b, err := strconv.ParseBool(s)

变量b的类型为布尔值。同样,布尔值也可转换为字符串。s := strconv.FormatBool(true)fmt.Println(s)

程序清单2.8是一个将布尔值转换为字符串的示例。

程序清单2.8 类型转换和类型检查 1: package main 2: 3: import ( 4:   "fmt" 5:   "strconv" 6:   "reflect" 7: ) 8: 9: func main() {10:   var b bool = true11:   fmt.Println(reflect.TypeOf(b))12:   var s string = strconv.FormatBool(true)13:   fmt.Println(reflect.TypeOf(s))14: }TRY IT YOURSELF▼ 类型转换在这个示例中,您将明白如何使用strconv包来执行类型转换。1.在文本编辑器中打开文件hour02/example08.go,并尝试理解这个示例是做什么的。2.在终端中执行命令go run example08.go以运行这个程序。3.您将在控制台中看到显示的类型,这表明已经将布尔数据转换成了字符串。  bool  string▲

 提示:理解数据结构。在编程中,错误地理解数据类型通常会导致Bug出现。使用数据源前,请先花点时间搞明白数据类型。如果数据源为数据库,请了解数据库模式(schema)及其使用的数据类型,这将节省大量的调试时间!2.7 小结

本章简要地介绍了数据类型。您知道了强类型语言和动态类型语言的差别以及它们的优缺点,了解了Go语言中一些基本数据类型,学习了如何检查变量的数据类型以及如何进行类型转换。本章介绍的内容很多,而且包含了一些基本的计算知识。2.8 问与答

问:字符串“1234”为何是字符串,而不是数字?

答:不管字符串看起来有多像数字,它都是字符串。要将其作为数字使用,必须先转换为数字类型。

问:数组能存储不同类型的数据吗?

答:能。有关这样的示例,请参阅第6章内容。

问:我熟悉C等其他语言。请问在Go语言中,我需要负责分配内存吗?

答:Go负责分配内存和执行垃圾收集。虽然正常的内存使用规则依然适用,但您无须直接管理内存。2.9 作业

作业包含小测验和答案,旨在加深对本章内容的理解。请尽可能先回答所有的问题再看后面的答案。2.9.1 小测验

1.强类型语言有何优缺点?

2.带符号整数和无符号整数有何不同?

3.如何检查变量的类型?2.9.2 答案

1.强类型语言的数据完整性更高,且编译器通常能够在代码执行前发现Bug。与使用动态类型语言相比,使用强类型语言时,开发速度可能慢一些,条条框框也多一些。鉴于强类型语言过于严格且编译速度缓慢,Go语言应运而生,旨在兼具动态类型语言的速度与灵活性和静态类型语言的性能与完整性。

2.无符号整数没有占据位的符号。4位无符号整数的可能取值为16个,只能为正;4位带符号整数的可能取值也是16个,但可正可负。

3.要检查变量的类型,可使用reflect包。要了解reflect包,请参阅程序清单2.6。2.10 练习

1.列举本章介绍的数字类型。阐述不同数据类型的差别,如果必要请参阅本章前面的内容。

2.创建一个简短的程序,将字符串变量和int变量之间进行转换。

3.如果有时间,请观看Gary Bernhardt的讲解视频WAT。该视频谈论了包括JavaScript在内的动态类型语言。切忌不分青红皂白地全盘接受!第3章 理解变量

本章介绍如下内容。● 变量是什么?● 快捷变量声明。● 理解变量和零值。● 编写简短变量声明。● 哪种变量声明方式更好?● 变量作用域。● 使用指针。● 声明常量。

变量是计算机程序不可或缺的部分。本章介绍如何在Go程序中创建和使用变量,还将介绍Go语言中的变量声明方式和变量作用域。3.1 变量是什么

如果您使用过其他语言进行编程,就不会对变量感到陌生。变量就是值的引用,是实现程序逻辑的基石之一。在Go语言中,声明变量的方式有多种。第2章介绍过,Go是一种静态类型语言,因此声明变量时必须显式或隐式地指定其类型。在程序清单3.1中,声明了一个名为s的变量,其类型为string。

程序清单3.1 声明string变量 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var s string = "Hello World" 9:   fmt.Println(s)10: }

对程序清单3.1解读如下。

1.使用关键字var声明一个变量。

2.这个变量名为s。

3.这个变量的类型为string。

4.赋值运算符=表示将它右边的值赋给变量。

5.将字符串字面量Hello World赋给变量s。

6.标准库中的fmt包通过变量s来引用其值,并将这个值传递给方法Println。

7.打印s的值。

程序清单3.1中,在声明变量的同时给它赋值,但也可在声明变量后再给它赋值,如程序清单3.2所示。

程序清单3.2 声明变量后再给它赋值 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6 7: func main() { 8:   var s string 9:   s = "Hello World"10:   fmt.Println(s)11: }

第2章说过,变量的类型很重要,因为这决定了可将什么值赋给变量。例如,对于类型为string的变量,不能将整数值赋给它;同理,不能将字符串赋给布尔变量。将类型不正确的值赋给变量时,将导致编译错误。在程序清单3.3中,将字符串赋给了类型为int的变量。

程序清单3.3 将类型不正确的值赋给变量 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var i int 9:   i = "One"10:   fmt.Println(i)11: }

运行这个示例将出现编译阶段错误,因为其中的代码试图将字符串赋给整型变量。单词One不是整数,不能将其赋给整型变量。go run example03.go# command-line-arguments./example03.go:7: cannot use "One" (type string) as type int in assignment3.2 快捷变量声明

Go支持多种快捷变量声明方式。可在一行内声明多个类型相同的变量并给它们赋值,如程序清单3.4所示。

程序清单3.4 快捷变量声明 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var s, t string = "foo", "bar" 9:   fmt.Println(s)10:   fmt.Println(t)11: }

对于不同类型的变量,可使用程序清单3.5所示的语法来声明。

程序清单3.5 以快捷方式声明类型不同的变量 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var ( 9:     s string = "foo"10:     i int = 411:   )12:   fmt.Println(s)13:   fmt.Println(i)14: }

声明变量后,就不能再次声明它。虽然可以给变量重新赋值,但不能重新声明变量,否则将导致编译阶段错误。var s int = 1fmt.Println(s)// This is not permittedvar s string = "Hello World"3.3 理解变量和零值

在Go语言中,声明变量时如果没有给它指定值,则变量将为默认值,这种默认值被称为零值。这不同于其他语言,因为在这些语言中,未赋值的变量的值为nil或undefined。程序清单3.6演示了变量的默认值。变量的默认值取决于其类型。

程序清单3.6 变量的零值 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var i int 9:   var f float6410:   var b bool11:   var s string12:   fmt.Printf("%v %v %v %q\n", i, f, b, s)13: }TRY IT YOURSELF▼ 变量默认被初始化为零值在这个示例中,您将明白Go如何初始化未指定值的变量。1.打开本书代码示例中的hour03/example06.go。2.在终端中执行命令go run example06.go运行这个程序。3.您将在控制台中看到各个变量的零值。  go run example06.go  0 0 false ""▲

使用变量时,知道Go语言的这种设计决策很重要。不久后,您就可能需要检查变量是否赋值了。注意,在Go语言中,为确定变量是否已经赋值,不能检查它是否为nil,而必须检查它是否为默认值。由于类型string的零值为" ",因此对于类型为string的变量,要确定是否已经给它赋值,可检查其值是否为零值" ",如程序清单3.7所示。

程序清单3.7 检查变量的值是否为零值 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   var s string 9:   if s == "" {10:     fmt.Printf("s has not been assigned a value and is zero valued")11:   }12: }

Go禁止将变量初始化为nil值,因为这样做将导致编译阶段错误。3.4 编写简短变量声明

在函数中声明变量时,可使用更简洁的方式——简短变量声明。程序清单3.8演示了简短变量声明。

程序清单3.8 简短变量声明 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: func main() { 8:   s := "Hello World" 9:   fmt.Println(s)10: }

对程序清单3.8解读如下。

1.声明一个名为s的变量。请注意,这里没有指定关键字var和类型。

2.简短变量赋值语句:=表明使用的是简短变量声明,这意味着不需要使用关键字var,也不用指定变量的类型。同时这还意味着应将:=右边的值赋给变量。

3.将字符串字面量“Hello World”赋给变量s。

使用简短变量声明时,编译器会推断变量的类型,因此您无须显式地指定变量的类型。请注意,只能在函数中使用简短变量声明。3.5 变量声明方式

您可能注意到了,Go提供了多种变量声明方式。为完整起见,下面列出了所有的变量声明方式。var s string = "Hello World"var s = "Hello World"var t stringt = "Hello World"u := "Hello World"

该使用哪种方式呢?Go对此有一定的限制——不能在函数外面使用简短变量声明。在遵守这条规则的前提下,怎么做都可以。

当然,如何声明变量是风格问题。在同一行内声明变量并给它赋值时,Go语言设计者在标准库中遵循的约定如下:在函数内使用简短变量声明,在函数外省略类型。程序清单3.9演示了这种被普遍接受的约定。如果您查看Go源代码,将发现简短变量声明是最常用的变量声明方式。

程序清单3.9 惯用的变量声明 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: var s = "Hello World" 6 7: func main() { 8:   i := 42 9:   fmt.Println(s)10:   fmt.Println(i)11: }TRY IT YOURSELF▼ 惯用的变量声明在这个示例中,您将明白Go语言惯用的变量声明方式。1.打开本书代码示例中的hour03/example09.go。尝试理解各种不同的变量声明方式。2.在终端中使用命令go run example09.go运行这个程序。3.您将在控制台中看到各个变量的值。  Hello World  42▲3.6 理解变量作用域

术语作用域指的是变量在什么地方可以使用,而不是变量是在什么地方声明的。Go语言使用基于块的词法作用域。乍一看,术语词法作用域令人望而生畏,但您必须掌握其中的原理。词法是一个形容词,意思与语言的词汇表相关。这意味着Go定义了变量在什么地方可以引用,在什么地方无法引用。对编程来说,这很有必要,因为这样可根据引用变量的位置,确定引用的是哪个变量。在Go语言中,块是位于一对大括号内的一系列声明和语句,但可以是空的。

可使用通俗的语言前述概念做如下诠释。● 在Go语言中,一对大括号({})表示一个块。● 对于在大括号({})内声明的变量,可在相应块的任何地方访问。● 大括号内的大括号定义了一个新块——内部块。● 在内部块中,可访问外部块中声明的变量。● 在外部块中,不能访问在内部块中声明的变量。

简而言之,每个内部块都可访问其外部块,但外部块不能访问内部块。● 程序清单3.10显示了大括号定义的程序结构和变量作用域。每对

大括号都表示一个块。● 代码的缩进程度反映了块作用域的层级。在每个块中,代码都被

缩进。● 在内部块中,可引用外部块中声明的变量。

程序清单3.10 Go语言中的词法作用域 1: package main 2: 3: import ( 4:   "fmt" 5: ) 6: 7: var s = "Hello world" 8: 9: func main() {10:   fmt.Printf("Print 's' variable from outer block %v\n", s)11:   b := true12:   if b {13:     fmt.Printf("Printing 'b' variable from outer block %v\n", b)

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载