本文翻译于Milap Neupane Blog的Learning Golang — from zero to hero 前言 Go是一种开源编程语言,它使构建简单、可靠和高效的软件变得容易 Go 语言被设计成一门应用于搭载 ,Go语言支持各种不同的数据结构。 Go语言的内置包 fmt 该包实现格式化的I/O函数。 json Go语言中另一个有用的包是json包。这有助于对JSON进行编码/解码。 当出现错误类型时,可以识别Go语言程序中的错误。 并发 Go语言的构建考虑到了并发性。Go语言中的并发性可以通过轻量级线程go routine语法来实现。 goroutine goroutine是可以与其他函数并行或并发运行的函数。
在 Go 语言中,常量是指编译期间就已知且不可改变的值,常量只可以是数值类型(包括整型、 浮点型和复数类型)、布尔类型、字符串类型等标量类型。 和 PHP 一样,在 Go 语言中,我们可以通过 const 关键字来定义常量(遵循 C 语言的约定)。 语言变量定义方式,可以看到 Go 这种变量和常量的声明方式可读性很好,从左往右,第一个标识符 var 或 const 表明声明的是变量还是常量,第二个标识符标识变量或常量的内存存储块别名,以便后续引用 预定义常量 Go 语言预定义了这些常量:true、false 和 iota。 Go 语言并不支持其他语言用于表示枚举的 enum 关键字,而是通过在 const 后跟一对圆括号定义一组常量的方式来实现枚举。
Go 语言的设计者作为行业老将,自然不会忽略这一点。说到这里,我们来看看 Go 语言的主要设计者都是何方神圣: ? 个顶个的都是大神级人物。 早期 Go 语言使用 makefile 作为临时方案,到了 Go 1 发布时引入了强大无比的 Go 命令行工具,Go 命令行工具彻底消除了工程文件的概念,完全用目录结构和包名来推导工程结构和构建顺序。 与之相比,Go 语言则要简单的多,针对只有一个源文件的情况(如上篇教程所示),引入工程管理看起来比较多余,因为直接用 go run 和 go build 搞定,下面我们通过 Go 语言构建一个简单的计算器项目来演示 Go 语言的基本工程管理方法。 Go 语言变量声明和初始化我们后面还会详细介绍,这里简单了解下即可。
安装 Go 使用 Go 语言之前,首先要安装 Go。 第一个 Go 程序 选择好了开发工具,接下来,就可以直接开始编写第一个 Go 语言程序了,还是遵循编程语言的一贯传统,我们从 Hello World 开始 Go 语言学习之旅。 首先,我们进入用户根目录,并在该目录下创建一个 go 目录,用来存放所有的 Go 语言代码: cd ~mkdir go 之所以在这里位置创建这个目录来存放代码,是因为 Go 语言默认的 GOPATH 环境变量值就是该路径 包是 Go 语言里最基本的分发单位,也是工程管理中依赖关系的体现。 要生成 Go 可执行程序,必须建立一个名字为 main 的包,并且在该包中包含一个叫 main() 的主函数,该函数是 Go 可执行程序的执行起点,这一点和 C 语言和 Java 语言很像,后续编译 Go
n", func_num_args()); printf("The sum of these numbers are %d\n", $sum); } sum(1, 2, 3, 4, 5); Go 语言中的变长参数 基本定义和传值 合适地使用变长参数,可以让代码更简洁,尤其是输入输出类函数,比如日志函数。 接下来,作为对比,我们来介绍下 Go 语言中的变长参数的用法,和 PHP 类似,只是把 ... 任意类型的变长参数 PHP 是弱类型语言,声明变长参数时不需要指定参数类型,Go 语言则不同,但是用过 fmt.Printf 函数的同学可能知道,我们可以向其中传递任意类型的参数值,可见 Go 语言也可以支持传递任意类型的值作为变成参数 答案是可以指定变长参数类型为 interface{}(空接口类型可以用于表示任意类型,后面我们在 Go 语言面向对象编程中会具体介绍),下面是 Go 语言标准库中 fmt.Printf() 的函数原型:
Go 语言提供了一些不需要导入任何包就可以直接使用的内置函数。我们把这些内置函数做一个简单的分类,如下表所示: ? 注:关于 Go 语言内置函数还可以参考 built 包文档。 在 Go 语言中,引用类型包括切片(slice)、字典(map)和管道(channel),其它都是值类型。
Go 语言的流程控制和 PHP 类似,支持如下的几种流程控制语句: 条件语句:用于条件判断,对应的关键字有 if、else 和 else if; 选择语句:用于分支选择,对应的关键字有 switch、case 在实际的使用中,往往会根据具体的业务逻辑,灵活组合上述控制语言来实现相应的功能。 接下来,我们来简单介绍下各种流程控制语句的用法,首先从条件语句开始。 something } else if condition2 { // do something else } else { // catch-all or default } 有其他编程语言基础的同学理解起来毫不费力 与 PHP 相比,关于 Go 语言的条件语句,需要注意以下几点: 条件语句不需要使用圆括号将条件包含起来 (); 无论语句体内有几条语句,花括号 {} 都是必须存在的; 左花括号 { 必须与 if 或者
Go 语言的分支语句和 PHP 类似,只是不需要在每个分支结构中显式通过 break 语句退出: switch var1 { case val1: ... 在 Go 语言中,我们可以用逗号分隔不同的分支条件来达到合并分支语句的目的,如 case 90,100,而不能像其它语言(如 PHP)那样,通过多个相邻的 case 语句来合并相同的分支语句,比如上面的 case 60 和 case 65,因为 case 60 这个分支语句在 Go 语言中会被认为是空语句,直接退出了。 综上,在 Go 语言中使用 switch...case... 分支语句时,需要注意以下几点: 和条件语句一样,左花括号 { 必须与 switch 处于同一行; 单个 case 中,可以出现多个结果选项(通过逗号分隔); 与其它语言不同,Go 语言不需要用 break
在Go语言的Web开发领域,Gin框架无疑是一个备受关注的轻量级框架。它具有快速、高效、易用等特点,非常适合用于构建Web应用程序。 Gin 是一个用 Go 语言编写的 Web 框架,它提供了快速构建高性能 Web 应用程序的工具和框架。 在Go语言的环境下,可以通过以下命令来安装Gin: go get -u github.com/gin-gonic/gin 创建第一个Gin应用 接下来,我们将创建一个简单的Gin应用程序。 安装和配置 Gin 框架 安装 Go 编程语言:首先,你需要安装 Go 编程语言。 2.插件系统和扩展功能 Gin 框架本身并没有官方支持的插件系统,但你可以通过 Go 语言的包管理系统来引入第三方库以扩展框架的功能。
基本使用 与其它编程语言不同的是,Go 语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构。 无限循环 Go 语言不支持 while 和 do-while 循环语句,对于无限循环场景的话,可以通过不带循环条件的 for 语句实现,下面我们通过无限循环来改写上述计算 1 到 100 以内数字之和的实现如下 for-range 结构 另外,对于可迭代的集合(数组、切片、字典),Go 语言还支持通过 for-range 结构对其进行循环遍历,关于这个循环结构的使用我们前面已经演示过,比如我们要遍历上面的切片 注意事项 综上,在 Go 语言中使用循环语句时,需要注意以下几点: 和条件语句、分支语句一样,左花括号 { 必须与 for 处于同一行; 不支持 whie 和 do-while 结构的循环语句; 可以通过 for-range 结构对可迭代集合进行遍历; 支持基于条件判断进行循环迭代; 与 PHP 一样,都允许在循环条件中定义和初始化变量,且支持多重赋值; Go 语言的 for 循环同样支持 continue
递归函数的编写思路 很对编程语言都支持递归函数,所谓递归函数指的是在函数内部调用函数自身的函数,从数学解题思路来说,递归就是把一个大问题拆分成多个小问题,再各个击破,在实际开发过程中,某个问题满足以下条件就可以通过递归函数来解决 通过斐波那契数列求解做演示 下面我们就以递归函数的经典示例 —— 斐波那契数列为例,演示如何通过 Go 语言基于上述归纳的思路编写递归函数来打印斐波那契数列。
new关键字 我们可以通过new关键字来创建一个结构体的实例,这种方法和其他语言比较类似,这样会得到一个空结构体指针,当中所有的字段全部填充它类型对应的零值。 所以创建一个结构体指针可以这样: func main() { p := &Point{} fmt.Print(p) } golang当中取地址符和声明指针的关键字和C语言是一样的,对于熟悉C语言的同学来说 Python当中对于继承的定义已经非常简洁了,实现起来大概是这样的: class A: pass class B(A): pass 直接在类名的后面就加上继承的信息,实际上绝大多数主流语言也都是这么干的
break 与 continue 语句 和 PHP 一样,Go 语言支持在循环语句中通过 break 语句跳出循环,通过 continue 语句进入下一个循环。 标签 Go 语言的 break 和 contine 与 PHP 的不同之处在于支持与标签结合跳转到指定的标签语句,从而改变这两个语句的默认跳转逻辑,标签语句通过标签+「:」进行声明: arr := [] goto 语句 goto 语句被多数语言学者所反对,告诫大家不要使用,因为很容易造成代码逻辑混乱,容易导致不易发现的 bug。 但 Go 语言仍然支持 goto 关键字,goto 语句的语义非常简单,就是跳转到本函数内的某个标签,如: arr := [][]int{{1,2,3},{4,5,6},{7,8,9}} for i
."); }); 可以看到,匿名函数是一种不需要定义函数名的函数声明方式,在多种编程语言中都有实现和支持,比如 PHP、JavaScript(想想 ajax 的实现)等,Go 语言中也提供了对匿名函数的支持 ,并且形式上和 PHP 类似,无非是要声明参数类型和返回值类型而已: func(a, b int) int { return a + b } 和 PHP 一样,Go 语言的匿名函数可以赋值给一个变量或者直接执行 注:所谓第一类对象指的是运行期可以被创建并作为参数传递给其他函数或赋值给变量的实体,在绝大多数语言中,数值和基本类型都是第一类对象,在支持闭包的编程语言中(比如 Go、PHP、JavaScript、Python 等),函数也是第一类对象,而像 C、C++ 等不支持闭包的语言中,函数不能在运行期创建,所以在这些语言中,函数不是不是第一类对象。 Go 语言中闭包的应用场景 Go 语言中的闭包同样也会引用函数外定义的变量,只要闭包还在被使用,那么被闭包引用的变量会一直存在。 下面我们来看一下 Go 语言中闭包的几个应用示例。
数组的声明和初始化 数组是所有语言编程中最常用的数据结构之一,Go 语言也不例外,与 PHP、JavaScript 等弱类型动态语言不同,在 Go 语言中,数组是固定长度的、同一类型的数据集合。 和 PHP 一样,Go 语言也通过 [] 来标识数组类型,以下是一些常见的数组声明方法: var a [8]byte // 长度为8的数组,每个元素为一个字节 var b [3][3]int // 二维数组 数组的长度是该数组类型的一个内置常量,可以用 Go 语言的内置函数 len() 来获取: arrLength := len(arr) 注:PHP 数组非常强大,囊括了常规的数组(Array)、集合(Set )、列表(List)、字典(Map)等数据结构,Go 语言的数组和大多数其他静态语言的数组一样,索引只能是数字,在 PHP 中,我们把索引是数字的数组叫做索引数组,把索引包含字符串的数组叫做关联数组,所以 Go 语言中的数组可以对照 PHP 中的索引数组来理解,不能是那种包含字符串键值对的关联数组。
通常情况下语言入门前会讲一堆背景和特性,目的是为了能让学习者对该语言有一个大概的认识,但这里我想直接进入细节,不是因为任性,而是因为常量是编程语言最基本的组成元素,这与语言背景无关。 当然可以,要知道GO语言是最懂程序员的哟 :) const PI = 3.1415926535897932 const EluerE = 2.718281828459045 const value = GO是怎么区分常量/变量是对内还是对外的呢? ---- 【编后话】: 开始接触GO,感觉它就是一个大杂烩,里面即有C语言的影子,也有Java语言的影子,也有JavaScript脚本的影子,同时还有Pascal语言的痕迹,但使用使用着感觉这符合人的正常思维 借用知乎用户的话讲:GO语言是一门看似简单实际并不简单,貌似外表丑陋实则另有考究的语言。 ----
Go编程语言提供称为数组的数据结构,其可存储相同类型的元素的一个固定大小的连续集合。数组用于存储数据的集合,但它往往是更加有用认为数组作为相同类型的变量的集合。 声明数组 要声明在Go语言数组,程序员指定元素的类型以及如下的数组所需元件的数目: var variable_name [SIZE] variable_type 这就是所谓的一维数组。 = 104 Element[5] = 105 Element[6] = 106 Element[7] = 107 Element[8] = 108 Element[9] = 109 数组是很重要的在Go 语言中,应该需要了解更多的细节。 有下列关系到数组几个重要的概念Go程序员是应该清楚的: 概念 描述 多维数组 Go支持多维数组。
支持的数据类型 Go 语言内置对以下这些基本数据类型的支持: 布尔类型:bool 整型:int8、byte、int16、int、uint、uintptr 等 浮点类型:float32、float64 复数类型 还对整型的精度及是否有符号(正数还是负数)做了区分,PHP 则只有一个 int 类型标识整型数据,另外 PHP 通过 float 和 double 来区分浮点型精度,这一点也是 Go 语言 和 PHP Go 语言还把接口单独作为一个类型提出来,后面介绍 Go 语言面向对象编程的时候会详细介绍这两个类型的使用。 布尔类型 Go 语言中的布尔类型与 PHP 差不多,关键字为 bool,可赋值且只可以赋值为预定义常量 true 和 false。 "0" 不包括任何元素的数组 特殊类型 NULL(包括尚未赋值的变量) 从空标记生成的 SimpleXML 对象 而在 Go 语言中则不然,甚至不同类型的值直接不能使用 == 或 !
同为类 C 语言,Go 语言的函数和 PHP 函数的基本结构差不多,只是具体细节有所差异,在 Go 语言中,函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句,作为强类型语言 在 Go 语言中,函数主要有三种类型: 普通函数 匿名函数(闭包) 类方法 我们将从普通函数的基本定义和调用开始,揭开 Go 函数的面纱。 变量一样,将类型放在最后,而与其他静态强类型语言,如 Java、C 的函数声明方式不同): func add(a, b int) int { // ... } 此外,Go 函数还支持多个返回值 函数即相当于其它语言的 public 函数,Go 语言中没有 public、protected、private 之类的关键字,它是通过首字母的大小写来区分可见性:首字母小写的函数只能在同一个包中访问, 首字母大写的函数才可以在其他包中调用,Go 文件中定义的全局变量也是如此。
单元测试 编写单元测试 在 Go 语言中,支持为功能模块编写单元测试代码,继续以上篇教程构建的计算器项目为例,在 simplemath 包中,我们可以为每一个运算模块编写了对应的单元测试代码,单元测试文件以 _test 作为文件名后缀来标识,比如我们通过 add_test.go 和 sqrt_test.go 文件分别为 add.go 和 sqrt.go 编写单元测试,对应的目录结构如下: ? 当然,这里我们只是介绍了最基本的单元测试实现,更加复杂的测试实现,我们后面在介绍 Go 语言特性时还会提到。 GDB 调试 GDB 是一个由 GNU 开源组织发布的、Unix/Linux 操作系统下的、基于命令行的、功能强大的程序调试工具,Go 语言编译后的二进制文件支持通过 GDB 进行调试,比如上篇教程通过 至此,Go 语言零基础入门三步曲已经完结,分别是第一个 Go 程序、简单的工程管理、单元测试及问题追踪,下一篇起,我们将正式开始介绍 Go 语言的语言特性、面向对象编程、并发编程、网络编程等高级使用指南