1 特性
- 标准库就考虑性能, 但却是编译型语言
- 跨平台
- 类
C, 强类型 - 带垃圾回收
- Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。( 果然, 新语言就是没有语言包袱, 想怎么设计就怎么设计, )
2 用的公司
- 腾讯
- 美团
- 滴滴
3 why go
- 最初使用的Python由于性能问题换成了Go
- C++不太适合在线Web业务早期
- 内部RPC和HTTP框架的推广
- 如果你要创建系统程序,或者基于网络的程序,Go语言是很不错的选择。
- 携程等并发模型
OOP 与 Go
Go 语言在设计上不是一种典型的面向对象编程语言,而是一种以并发和简洁为主要目标的编程语言。尽管如此,Go 语言仍然支持面向对象编程的一些概念和特性。
Go 语言通过结构体(struct)和方法(method)来实现对面向对象编程的支持。结构体可以用于封装数据和行为,并且可以定义方法来操作结构体实例。这样就能够实现面向对象编程中的封装、继承和多态等概念。
尽管 Go 语言没有经典面向对象语言中的类(class)的概念,但可以使用结构体和方法组合来模拟类的行为。通过在结构体上定义方法,可以实现对结构体的操作和行为的封装。
除了结构体和方法,Go 语言还提供了接口(interface)的概念,它定义了一组行为规范。通过实现接口,可以实现多态的效果,使不同类型的对象可以根据接口进行统一的处理。
需要注意的是,Go 语言更强调简洁和可读性,相比于传统的面向对象编程语言,Go 语言更加注重可组合性和函数式编程的思想。因此,在使用 Go 语言进行开发时,可以灵活地选择使用面向对象编程的特性来组织代码结构,或者使用其他更适合的编程范式。
// c 风格 api
s = append(s, "d")
s = append(s, "e", "f")
// 对象式
学习平台
短链接:hi-hi.cn/gitpod
gitpod 这个效果还挺好看
编译与运行
单文件
# 运行
go run helloworld.go
# 编译
go build helloworld.go
语法
- 没有括号
- 变量类型后置
- 支持返回多个值
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
如何组织代码
- Go语言的代码通过包(package)组织,包类似于其它语言里的库(libraries)类推==>
STL或者模块(modules)python。一个包由位于单个目录下的一个或多个.go源代码文件组成,目录定义包的作用。每个源文件都以一条package声明语句开始,这个例子里就是package main,表示该文件属于哪个包,紧跟着一系列导入(import)(python)的包,之后是存储在这个文件里的程序语句。 类似于pythonGo语言不需要在语句或者声明的末尾添加分号,除非一行上有多条语句。实际上,编译器会主动把特定符号后的换行符转换为分号,因此换行符添加的位置会影响Go代码的正确解析(译注:比如行末是标识符、整数、浮点数、虚数、字符或字符串文字、关键字break、continue、fallthrough或return中的一个、运算符和分隔符++、--、)、]或}中的一个)- Go语言在代码格式上采取了很强硬的态度。
gofmt工具把代码格式化为标准格式,ctrl + s以后自动格式化, 妙蛙 - 包导入顺序并不重要;gofmt工具格式化时按照字母顺序对包名排序。(我看不懂, 大为震撼)
// 多个包
import{
"fmt"
"os"
}
func
类型与变量
- 类型不需要导入
- 可以使用
const修饰 - 短变量声明是一种简洁的变量声明方式,用于同时声明和初始化变量。
var b, c int = 1, 2
var e float64
// 短变量声明
f := a
// 数组
var a [5]int
b := [5]int{1, 2, 3, 4, 5}
// 多维数组
var twoD [2][3]int
// 无力吐槽了 int* arr = new int[size];
s := make([]string, 3)
// c 风格 api
s = append(s, "d")
s = append(s, "e", "f")
// ------------map-------------
m := make(map[string]int)
new 和 make
- 也是像
C++
在 Go 语言中,make 和 new 是两个用于创建对象的关键字,但它们用途不同。
-
new:new用于创建各种类型的指针,并分配了零值。例如,使用new可以创建一个指向整数、结构体或数组的指针,而指针指向的内容会被初始化为对应类型的零值。对于数组来说,返回的是指向数组的指针。var p *int = new(int) // 创建一个指向 int 类型的指针,并初始化为零值 fmt.Println(*p) // 输出:0 var arr *[]int = new([]int) // 创建一个指向 int 类型切片的指针,并初始化为零值 fmt.Println(*arr) // 输出:[] -
make:make用于创建切片、映射和通道等引用类型的对象,并进行初始化。它会分配内存并返回一个已经初始化的非零值对象。对于切片、映射和通道来说,返回的是对象本身(非指针)。slice := make([]int, 5, 10) // 创建一个长度为 5,容量为 10 的 int 类型切片 fmt.Println(slice) // 输出:[0 0 0 0 0] m := make(map[string]int) // 创建一个 key 为字符串,value 为整数的映射 m["foo"] = 42 fmt.Println(m) // 输出:map[foo:42] ch := make(chan int) // 创建一个整数类型的通道
控制流
for j := 7; j < 9; j++ {
fmt.Println(j)
}
// 大为震撼.jpg
for {
// ...
}
// else 空行不限制
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
函数和方法
函数
- 类型在变量名后
- 如果你有多个参数的类型相同,你可以进行简写,只需要在这几个相同的参数最后写一遍类型即可。
- 函数可以有 0 个或多个返回值。和参数不同,有几个返回值就写几个返回值类型,不能简写。
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(1, 2))
}
通过给返回值进行命名,使用空 return 语句,这样会直接返回已命名的返回值。
func sumAndDiff(x, y int) (sum int, diff int) {//提前命名返回值
sum = x + y
diff = x - y //返回值在函数中被初始化
return //返回值已经初始化了,不需要再在return语句中写变量了
}
导出
- 在 Go 语言中,如果一个名字以大写字母开头,那么它就是已导出的,这意味着别的包可以使用它。(相当于 Java 中的
public的作用) - 比如我们常用的打印函数
fmt.Println(...),可以看到Println()的首字母是大写的,所以我们能够导入fmt包后使用该方法。
方法
- Go 中也有类似于面向对象中方法的概念,也叫方法(
method),这种方法其实是一种特殊的函数(function)—— 带有接收者(receiver)的函数。 - 通过
.可以调用方法 - 通过交换
函数名以及函数参数来区分函数以及方法 - 有点类似于传入指针
package main
import "fmt"
type dog struct {
name string
}
func (d dog) say() {//方法
fmt.Println(d.name + " 汪汪汪。。。方法")
}
func main() {
d := dog{"哮天犬"}
d.watchDoor()
}
可以实现一种多态性
- 相同的方法名, 但是不同的对象(结构体)调用
package main
import "fmt"
type dog struct {
name string
}
type cat struct {
name string
}
type rabbit struct {
name string
}
// 使用 函数来实现, 需要不同的函数名
func dogSay(d dog) {
fmt.Println(d.name + " 汪汪汪。。。函数")
}
func catSay(c cat) {
fmt.Println(c.name + " 喵喵喵。。。函数")
}
func (d dog) say() {
fmt.Println(d.name + " 汪汪汪。。。方法")
}
// 使用方法来实现, 相同的函数名就可以
func (c cat) say() {
fmt.Println(c.name + " 喵喵喵。。。方法")
}
func (r rabbit) say() {
fmt.Println(r.name + " 吱吱吱。。。方法")
}
func main() {
d := dog{"哮天犬"}
c := cat{"加菲猫"}
r := rabbit{"玉兔"}
d.say() //调用
c.say()
r.say()
}
常用的包
fmt
fmt.Println("hello world")