package main
import "fmt"
func main(){
fmt.Println("hello,world!")
fmt.Println(sum(1,2))
fmt.Printf("Καλημέρα κόσμε; or こんにちは 世界\n")
}
func sum(a,b int) int {
return a+b
}
数据类型
- 使用var声明的变量的值会自动初始化为该类型的零值
- 基本类型:int、float、bool、string
- 结构化(复合):struct、array、slice、map、channel
- 只描述类型的行为的:interface
- 结构化类型没有真正的值,使用nil作为默认值
- Go语言中不存在类型的继承
- 使用type关键字可以定义自己的类型,但也可以定义一个已经存在的类型的别名
type IZ int
var a IZ = 5
函数的多返回值,返回类型之间需要使用逗号分隔开,并使用小括号括起来
Go程序的一般结构
package main
import (
"fmt"
)
const c = "C"
var v int = 5
type T struct{}
func init() { // initialization of package
}
func main() {
var a int
Func1()
// ...
fmt.Println(a)
}
func (t T) Method1() {
//...
}
func Func1() { // exported function Func1
//...
}
1、完成包的import之后,开始对常量、变量和类型的定义或声明
2、存在init函数,对这个函数定义
3、如果当前是main包,定义main函数
4、定义其他函数,首先是类型的方法,接着按照main函数中先后调用的顺序来定义相关函数
类型转换
a := 5.0
b := int(a)
- 取值范围较小的类型转换到一个取值范围较大的类型
- 从取值范围较大的转换到取值范围较小的类型时会发生精度丢失的情况
- 具有相同底层类型的变量之间可以相互转换
var a IZ = 5
c := int(a)
d := IZ(c)
常量
常量使用关键字
const
定义,用于存储不会改变的数据,只可以是布尔型、数值型(整数、浮点数)和字符串类型
const PI=3.14159
- 没有被指定类型的常量被使用会根据使用环境推断它所具备的类型
- 常量的值必须能够在编译时就能够确定(不能通过自定义函数赋值,内置函数可以)
const beef, two, c = "eat", 2, "veg"
const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)
const (
Unknown = 0
Female = 1
Male = 2
)
// iota可用作枚举值
const(
a=iota
b=iota
c=iota
)
//第一个iota=0,每当新的iota被使用时,值自动加1
//a=0,b=1,c=2
//也可简写为以下:
const (
a = iota
b
c
)
//在每遇到一个新的常量块或单个常量声明时, iota 都会重置为 0( 简单地讲,每遇到一次 const 关键字,iota 就重置为 0 )
变量
- 声明变量的形式一般使用
var
关键字var identifier type
var a,b *int
//指针类型
var a int
var b bool
var str string
var (
a int
b bool
str string
)
- 一个变量(常量、类型或函数)在程序中都有一定的作用范围,称为作用域。
- 如果一个变量在函数体外声明,则被认为是全局变量,可以在整个包甚至外部包(被导出后)使用,不管声明在哪个源文件或哪个源文件里调用该变量。
- 在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。
var a = 15
var b = false
var str = "Go says hello to the world!"
- 当你在函数体内声明局部变量时,应使用简短声明语法
:=
a:=1
值类型和引用类型
- 所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值。
- 数组和结构等复合类型也是值类型。
- 可以通过 &i 来获取变量 i 的内存地址。
- 更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。
- 指针、slices、maps、channel属于引用类型
- 被引用的变量会存储在堆中,以便进行垃圾回收,且比栈拥有更大的内存空间。
- 一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。
- 内存地址称为指针。
- 同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。
当使用赋值语句 r2 = r1 时,只有引用(地址)被复制。
打印
- 格式化打印
%..
,..
可以被不同类型所对应的标识符替换%s
,字符串%v
,使用类型的默认输出格式的标识符
init函数
变量除了可以在全局声明中初始化,也可以在 init 函数中初始化。这是一类非常特殊的函数,它不能够被人为调用,而是在每个包完成初始化后自动执行,并且执行优先级比 main 函数高。
全局变量定义,init函数,main函数,执行流程是:全局变量定义->init函数->main函数
package trans
import "math"
var Pi float64
func init() {
Pi = 4 * math.Atan(1) // init() function computes Pi
}
package main
import (
"fmt"
)
var age = test()
func test() int {
fmt.Println("test()...")//1
return 90
}
func init() {
fmt.Println("init()...")//2
}
func main() {
fmt.Println("main()...")//3
fmt.Println("age = ", age)
}
//test()...
//init()...
//main()...
//age = 90
go_study
│
├─test
│ │ init.go
│ │
│ │
│ └─utils
│ utils.go
utils.go
package utils
import "fmt"
var Age int
var Name string
func init() {
fmt.Println("utils.init()...")
Age = 100
Name = "tom~"
}
init.go
package main
import (
"fmt"
"go_study/test/utils"
)
var age = test()
func test() int {
fmt.Println("test()...") //1
return 90
}
func init() {
fmt.Println("init()...") //2
}
func main() {
fmt.Println("main()...") //3
fmt.Println("age = ", age)
fmt.Println("utils.Age = ", utils.Age)
fmt.Println("utils.Name = ", utils.Name)
}
output
utils.init()...
test()...
init()...
main()...
age = 90
utils.Age = 100
utils.Name = tom~
执行流程: