学习一门编程语言需要哪些步骤 Link to heading

  1. 变量定义
  2. 数据类型
  3. 条件语句
  4. 循环语句
  5. 多态继承
  6. 业务抽象

个人认为掌握以上列出的 6 条,就已经掌握现代编程语言所需要的最基础以及最常用的内容。剩下的就是在使用中不断的累积该语言的规范,约定,API 及语法糖。

现代编程语言仍需掌握一个开发脚手架,例如 Ruby 语言拥有 Ruby On Rails,Sinatra。Python 拥有 Django,Php 拥有 larvael, Golang 拥有 Beego,Gin 等。

语言是框架的基础,框架是语言的业务实现。框架可以帮助开发人员,快速的将,现实生活的事物,抽象成计算机世界的对象,并且在计算机世界开始生活。

如果说 Ruby 是一门最程序员有好的语言,那么当先互联网 IT 行业最炙手可热的语言当数Golang了。我本人第一次听说 Golang 应该是在 2017 年末, 通过Docker了解到 Golang,

当时并没有对其产生兴趣,但后来先后有俩个同事从 Ruby 栈转到 Golang,同时北京的求职市场上Ruby可谓惨不忍睹,我也开始有一搭没一搭开始学习尝试使用 Golang。

说起来,从第一行Hello World代码,到后来使用Gin实现一些 API,到现在也有三年左右的时间。随着这次 Blog 迁移,我这里打算记录一下Ruby 程序员是如何一步步学习一门静态强类型语言的.


Golang 基础语法简介 Link to heading

常量、变量、类变量、临时变量、实例变量  , Ruby 的世界中关于变量的定于有许多种,其实日常工作中常用的也就几个。Golang 中仿佛关于变量的定义并没有 Ruby 那么区分,但还是有很大区别。

声明常量 Link to heading

Golang中的变量及常量于大部分静态语言基本一致,需要提前进行声明其中常量声明的关键字为const、变量声明关键字为var,相信这两个关键字大家都不陌生,尤其是经常和javascripttypescript打交道的朋友。当然 golang 也提供了更加方便的变量定义语句,以及类型推断机制,以提高程序员编码效率。下面我们看一下变量及常量在Golang中的一些表现:

package main

import "fmt"

// 常量 声明关键字 const

// 声明单独的包级常量
const Pi = 3.14
const Pai = Pi

// 声明一组包级常量
const (
	Age        = 25
	Name       = "张学友"
	Profession = "歌手"
	No         = !Yes
	Yes        = true
)

// 同时声明多个包级常量
const Addr, Number, Gender = "中国香港", "13100000000", "男"

func main() {
	fmt.Println(Pi)
	fmt.Println(Pai)
	fmt.Println(Age)
	fmt.Println(Name)
	fmt.Println(Profession)
	fmt.Println(Addr)
	fmt.Println(Number)
	fmt.Println(Gender)
	fmt.Println("No is", No)
	// fmt.Println("Yes is", Yes)

	// 声明局部常量
	const DoublePi = 2 * Pi
	fmt.Println("DoublePi is", DoublePi)
}
$ go run basic_const.go

3.14
3.14
25
张学友
歌手
中国香港
13100000000
No is false
DoublePi is 6.28

Go 白皮书把上面每行含有一个等号=的语句称为一个常量描述(constant specification)。 每个const关键字对应一个常量声明。一个常量声明中可以有若干个常量描述。 上面的例子中含有 5 个常量声明。除了第 3 个,其它的常量声明中都各自只有一个常量描述。 第 3 个常量声明中有 5 个常量描述。

在上面的例子中,符号*是一个乘法运算符, 符号!是一个布尔取否运算符。常量声明中的等号=表示“绑定”而非“赋值”。 每个常量描述将一个或多个字面量绑定到各自对应的具名常量上。 或者说,每个具名常量其实代表着一个字面常量。

常量可以直接声明在包中,也可以声明在函数体中。 声明在函数体中的常量称为局部常量(local constant),直接声明在包中的常量称为包级常量(package-level constant)。 包级常量也常常被称为全局常量。

包级常量声明中的常量描述的顺序并不重要。比如在上面的例子中, 常量描述NoYes的顺序可以掉换一下。

类型确定常量 Link to heading

我们可以在声明一些常量的时候指定这些常量的确切类型。 这样声明的常量称为类型确定具名常量。 在下面这个例子中,所有这 4 个声明的常量都是类型确定的。 XY的类型都是float32AB的类型都是int64

// go_basic_const01.go

package main

const X float32 = 3.14

// 同样可以使用显式类型转换
// const X = float32(3.14)

// 当然这里的现实类型转换必须是合法的
const a uint = 128

// 这里的 256 不能 显式转换为uint8
// const c = uint8(256) // error: 256溢出uint8

const (
	//
	A, B int64 = -3, 5

	Y float32 = 2.718
)

func main() {
	fmt.Println("a =>", a)
	fmt.Println("A =>", A)
	fmt.Println("B =>", B)
	fmt.Println("Y =>", Y)
}
v
$ go run go_basic_const01.go

a => 128
A => -3
B => 5
Y => 2.718

常量的自动补全 Link to heading

在一个包含多个常量描述的常量声明中,除了第一个常量描述,其它后续的常量描述都可以只包含标识符列表部分。 Go 编译器将通过照抄前面最紧挨的一个完整的常量描述来自动补全不完整的常量描述。 比如,在编译阶段,编译器会将下面的代码

// go_basic_const02.go
package main

import "fmt"

const (
	X float32 = 3.14
	Y         // 这里必须只有一个标识符
	Z         // 这里必须只有一个标识符

	A, B = "Go", "Ruby"
	C, _
)

func main() {
	fmt.Println("X =>", X)
	fmt.Println("Y =>", Y)
	fmt.Println("Z =>", Z)
	fmt.Println("A =>", A)
	fmt.Println("B =>", B)
	fmt.Println("C =>", C)
}
$ go run go_basic_const02.go
X => 3.14
Y => 3.14
Z => 3.14
A => Go
B => Ruby
C => Go

利用 iota 声明常量 Link to heading

iota是 Go 中预声明(内置)的一个特殊的具名常量。 iota被预声明为0,但是它的值在编译阶段并非恒定。 当此预声明的iota出现在一个常量声明中的时候,它的值在第 n 个常量描述中的值为n(从 0 开始)。 所以iota只对含有多个常量描述的常量声明有意义。

iota和常量描述自动补全相结合有的时候能够给 Go 编程带来很大便利。 比如,下面是一个使用了这两个特性的例子。 请阅读代码注释以了解清楚各个常量被绑定的值。

// basic_const_iota.go
package main

import "fmt"

const (
	k = 3 // 在此处,iota == 0

	m float32 = iota + .5 // m float32 = 1 + .5
	n                     // n float32 = 2 + .5

	p    = 9          // 在此处,iota == 3
	q    = iota * 2   // q = 4 * 2
	_                 // _ = 5 * 2
	r                 // r = 6 * 2
	s, t = iota, iota // s, t = 7, 7
	u, v              // u, v = 8, 8
	_, w              // _, w = 9, 9
)

const x = iota // x = 0 (iota == 0)
const (
	y = iota // y = 0 (iota == 0)
	z        // z = 1
)

// 实际业务中常用定义
const (
	Failed    = iota - 1 // == -1
	Unknown              // == 0
	Succeeded            // == 1
)

func main() {
	fmt.Println("m =>", m)
	fmt.Println("n =>", n)
	fmt.Println("q =>", q)
	fmt.Println("r =>", r)
	fmt.Println("s =>", t)
	fmt.Println("u =>", u)
	fmt.Println("v =>", v)
	fmt.Println("w =>", w)
	fmt.Println("Failed =>", Failed)
	fmt.Println("Unknown =>", Unknown)
	fmt.Println("Succeeded =>", Succeeded)
}
go run basic_const_iota.go

m => 1.5
n => 2.5
q => 8
r => 12
s => 7
u => 8
v => 8
w => 9
Failed => -1
Unknown => 0
Succeeded => 1