很久之前就想学Go语言了,但是一直有其他东西要学,因为我学的是Java嘛,所以后面学的东西一直是跟Java相关的。
最近来到公司实习,需要用到Go语言,所以就趁着这个机会把Go学了。
简单来说就是由Google公司的Robert Griesemer,Rob Pike和Ken Thompson设计的一种静态类型、编译型语言。它在2009年正式对外公开,目标是解决大规模软件工程中的问题。Go语言的语法简洁清晰,易于学习和使用,编译速度快,具有垃圾回收功能,并且拥有强大的标准库。
Go语言的主要目标是将静态语言的安全性和高效性与动态语言的易开发性进行有机结合,达到完美平衡,从而使编程变得更加有乐趣,而不是在艰难抉择中痛苦前行。Go语言设计最本质的初衷就是简单,希望程序员的工作量最小化,利用Go本身少量的特性,并通过组合的方式去解决实际问题。
因为之前学过Java和C语言,所以我就主要记录一下他们之间的区别。
我是用的vscode作为代码编辑器。
Go 语言的基础组成有以下几个部分:
接下来看下简单的代码,该代码输出了"Hello World!":
package main
import "fmt"
func main() {
/* 这是我的第一个简单的程序 */
fmt.Println("Hello, World!")
}
有点C语言的感觉有木有……
其实也和C语言差不多,和C语言不一样的有以下几个地方:
1、在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。
如果你打算将多个语句写在同一行,它们则必须使用 ; 人为区分,但在实际开发中我们并不鼓励这种做法。
go语言保留的关键字有:
2、此外,在 Go 语言中,空格通常用于分隔标识符、关键字、运算符和表达式,以提高代码的可读性。
Go 语言中变量的声明必须使用空格隔开,如:
var x int
const Pi float64 = 3.14159265358979323846
这是因为在运算符和操作数之间要使用空格能让程序更易阅读。我平时敲代码没有敲空格的习惯,但是每次保存后,他竟然会自动给我把该有的空格给打上去了,很神奇。可能是我装了什么插件?
对了,在go语言中IF表达式不用括号,我一开始不知道,后面因为我那个神奇的插件,每次我保存之后,他会默认给我把括号给干了,就像这样。
if x > 0 {
// do something
}
3、go语言的类型定义一般写在语句的最后面,举个例子:
//在C语言中,我们定义一个整型变量
int x ;
float pi = 3.14159265358979323846;
//而在go语言中,通常这样写
var x int
const Pi float64 = 3.14159265358979323846
//之后还会接触更简单的写法,像这样:
pi := 3.14159265358979323846
那么为什么go语言要把数据定义放在后面,而不是像Java一样,放在变量前面嘞?
因为数据类型放在变量名后面可以增加代码的可读性和可维护性。这种语法风格称为“后缀类型声明”。使用后缀类型声明,可以清晰地指定变量的数据类型,避免了在代码中使用多个变量时,由于数据类型不同而产生的混淆和错误。
此外,Go语言的这种设计还有另一个重要的原因:Go语言支持类型推断,也就是说,在许多情况下,你可以省略变量的类型,让Go语言自动推断。这样做可以使代码更简洁,也更符合人类的阅读习惯。
例如,在Go语言中,你可以写 var a = 20
。因为20是一个整数,所以Go语言可以自动推断出 a
的类型是 int
。如果把类型放在变量名前面,那么当你想省略类型时,变量名就必须放在等号的右边,这样就打破了我们通常的阅读习惯。
总的来说,Go语言把类型放在变量名后面,主要是为了提高代码的可读性、可维护性和简洁性。
数据类型蛮多的,详情点击这里:Go语言数据类型
问:为什么Go语言会有这么多数据类型嘞?比如 float 都分了一个“ float32 ”和“ float64 ”
这是因为Go语言的数据类型设计理念主要是为了提供更多的灵活性和效率。数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。
Go语言提供了多种多样的数据类型,这些数据类型可以满足各种编程需求,使得Go语言在处理复杂的数据结构时更加方便和高效。
此外,Go语言还提供了基于架构的类型,例如:int
、uint
和 uintptr
。这些类型的大小会根据运行程序的操作系统位数来确定,这样可以更好地利用硬件资源,提高程序运行效率。
相比之下,Java语言的数据类型设计相对简单一些,主要包括八种基本数据类型和引用数据类型。这是因为Java语言的设计目标是“ 一次编写,到处运行 ”,因此它在数据类型设计上追求的是跨平台性和易用性。
总的来说,Go语言在数据类型设计上提供了更多的选择和灵活性,以适应各种不同的编程需求和场景。
问:比如我写了一句a, b, c, d := 20, 10, 15, 5 ,他会默认用int8还是int16其他类型?为什么嘞
答:在Go语言中,当你使用 :=
进行变量声明和初始化时,Go会根据右侧的值自动推断出变量的类型。例如,代码 a, b, c, d := 20, 10, 15, 5
中,因为20、10、15和5都是整数,所以Go会自动推断 a
、b
、c
和 d
的类型为 int
。
这是因为Go语言的设计目标之一是代码的简洁性和易读性。通过自动类型推断,程序员可以省去在每次声明变量时都显式指定变量类型的麻烦,使得代码更加简洁易读¹。
至于为什么默认使用 int
而不是 int8
或 int16
,这是因为在大多数情况下,int
类型已经足够满足需求,并且可以提供更好的性能。在Go语言中,int
类型的大小会根据运行程序的操作系统位数来确定。这样可以更好地利用硬件资源,提高程序运行效率。
如果你需要使用特定大小的整数类型(如 int8
或 int16
),你可以在声明变量时显式指定类型。例如:var e int8 = 20
。这样,变量 e
的类型就会被明确地设置为 int8
。
简单总结一下这两天的使用体验:
// if, if else, else 语句
a := 10
if a == 10 {
fmt.Println("a 等于 10")
} else if a > 10 {
fmt.Println("a 大于 10")
} else {
fmt.Println("a 小于 10")
}
// for 循环
for i := 0; i < 5; i++ {
fmt.Println(i)
}
/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
/* 声明局部变量 */
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
package main
import "fmt"
/* 声明全局变量 */
var g int
func main() {
/* 声明局部变量 */
var a, b int
/* 初始化参数 */
a = 10
b = 20
g = a + b
fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)
}
var arrayName [size]dataType
其中,arrayName 是数组的名称,size 是数组的大小,dataType 是数组中元素的数据类型。
数组初始化
以下实例声明一个名为 numbers 的整数数组,其大小为 5,在声明时,数组中的每个元素都会根据其数据类型进行默认初始化,对于整数类型,初始值为 0。
var numbers [5]int
还可以使用初始化列表来初始化数组的元素:
var numbers = [5]int{1, 2, 3, 4, 5}
另外,还可以使用 := 简短声明语法来声明和初始化数组:
numbers := [5]int{1, 2, 3, 4, 5}
以上代码创建一个名为 numbers 的整数数组,并将其大小设置为 5,并初始化元素的值。
注意!如果数组长度不确定,可以使用 … 代替数组的长度,编译器会根据元素个数自行推断数组的长度:
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
如果设置了数组的长度,我们还可以通过指定下标来初始化元素:
// 将索引为 1 和 3 的元素初始化
balance := [5]float32{1:2.0,3:7.0}
访问数组元素没啥好说的,一维数组理解了,多维数组和函数传递数组也差不多了,传送门:Go语言多维数组,向函数传递数组
指针、结构体的定义就像之前变量的定义,然后用法和C语言基本一致,举两个栗子:
指针:
package main
import "fmt"
func main() {
var a int= 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a )
/* 指针变量的存储地址 */
fmt.Printf("ip 变量储存的指针地址: %x\n", ip )
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip )
}
结构体:
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
这些就是一些比较基础的语法了,在学习的过程中,可以多去敲敲代码,熟悉一下。也可以去菜鸟教程上面多看看,对新人挺友好的,也是我的公司同事推荐的。后续会不定期更新学习记录和一些学习实验吧