Go 语言基础语法

文章目录

  • 一、GO 语言结构
    • 1. 基础组成
    • 2. 实例
    • 3. 执行 Go 程序
  • 二、Go 语言基础语法
    • 1. Go 标记
    • 2. 行分隔符
    • 3. 注释
    • 4. 标识符
    • 5. 字符串连接
    • 6. 关键字
    • 7. Go 语言的空格
    • 8. 格式化字符串
  • 三、Go 语言数据类型
    • 1. 分类
    • 2. 数字类型
    • 3. 浮点型
    • 4. 其他数字类型
  • 四、Go 语言变量
    • 1. 变量声明
    • 2.变量声明方法
    • 3. 多变量声明
    • 4. 值类型和引用类型
      • 4.1 内存的压栈
      • 4.2 内存的堆
      • 4.3 示例
    • 5. 变量的作用域
    • 6. 简短形式,使用 := 赋值操作符
    • 7. 空白标识符
  • 五、常量
    • 1. 什么是常量
    • 2. 示例
    • 3. iota


一、GO 语言结构

1. 基础组成

包声明
引入包
函数
变量
语句&表达式
注释

2. 实例

package main

import "fmt"

func main() {
   /* 这是我的第一个简单的程序 */
	fmt.Println("hello world!")
}
  • 第一行代码 package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。

  • 下一行 import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。

  • 下一行 func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。

  • 下一行/*...*/是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

  • 下一行 fmt.Println(...) 可以将字符串输出到控制台,并在最后自动增加换行字符 \n。
    使用 fmt.Print(“hello, world\n”) 可以得到相同的结果。
    Print 和 Println 这两个函数也支持使用变量,如:fmt.Println(arr)。如果没+有特别指定,它们会以默认的打印格式将变量 arr 输出到控制台。

  • 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出;标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的。

3. 执行 Go 程序

执行go run test.go可以看到输出为hello world!
执行go build test.go可以生成二进制文件test.exe
Go 语言基础语法_第1张图片
Go 语言基础语法_第2张图片

二、Go 语言基础语法

1. Go 标记

  • Go 程序可以由多个标记组成,可以是
    关键字,标识符,常量,字符串,符号

  • 如以下 GO 语句由 6 个标记组成:

fmt.Println("Hello, World!")

//6 个标记是(每行一个):

fmt
.
Println
(
"Hello, World!"
)

2. 行分隔符

  • 在 Go 程序中,一行代表一个语句结束

  • 如果你打算将多个语句写在同一行,它们则必须使用;人为区分,但在实际开发中我们并不鼓励这种做法

  • 以下为两个语句:

fmt.Println("Hello, World!")
fmt.Println("百度:baidu.com")

3. 注释

  • 注释不会被编译,每一个包应该有相关注释

  • 单行注释是最常见的注释形式,你可以在任何地方使用以//开头的单行注释。

  • 多行注释也叫块注释,均已以/*开头,并以*/结尾。

// 单行注释
/*
 你好
 欢迎来南京
 */

4. 标识符

  • 标识符用来命名变量、类型等程序实体
  • 一个标识符实际上就是一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字
//以下是有效的标识符
mahesh   kumar   abc   move_name   a_123
myname50   _temp   j   a23b9   retVal
//以下是无效的标识符
1ab(以数字开头)
case(Go 语言的关键字)
a+b(运算符是不允许的)

5. 字符串连接

  • Go 语言的字符串可以通过 +实现:

  • 实例

package main
import "fmt"
func main() {
    fmt.Println("hello" + "world")
}

//以上实例输出结果为:

helloworld

6. 关键字

  • 下面列举了 Go 代码中会使用到的 25 个关键字或保留字:
. . . . .
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
  • 除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:
. . . . .
append bool byte cap close
copy false float32 float64 imag
int32 int64 iota len make
print println real recover string
  • 程序一般由关键字、常量、变量、运算符、类型和函数组成。

  • 程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}

  • 程序中可能会使用到这些标点符号:. , ; :

7. Go 语言的空格

  • Go 语言中变量的声明必须使用空格隔开
var age int;
//语句中适当使用空格能让程序更易阅读

//无空格:
fruit=apples+oranges;

//在变量与运算符间加入空格,程序看起来更加美观,如:
fruit = apples + oranges; 

8. 格式化字符串

  • Go 语言中使用 fmt.Sprintf 格式化字符串并赋值给新串
package main

import (
	"fmt"
)

func main() {
   // %d 表示整型数字,%s 表示字符串
	var age = 18
	var time = "2022-3-15"
	var url = "age=%d,time=%s"
	var target_url = fmt.Sprintf(url, age, time)
	fmt.Println(target_url)
}

输出结果为:

age=18,time=2022-3-15

常用的占位符

格式化指令 含义
%% %字面量
%b 将一个整数格式转化为二进制的表达方式
%c 相应Unicode码点对应所表示的字符
%d 十进制整数
%o 八进制整数
%x 小写的十六进制数值
%X 大写的十六进制数值
%U 一个Unicode表示法表示的整型码值
%s 输出以原生的UTF8字节表示的字符,如果console不支持utf8编码,则会乱码
%t 以true或者false的方式输出布尔值
%v 使用默认格式输出值,或者如果方法存在,则使用类性值的String()方法输出自定义值
%T 输出值的类型

三、Go 语言数据类型

1. 分类

  • 在 Go 编程语言中,数据类型用于声明函数和变量

  • 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存

  • Go 语言按类别有以下几种数据类型:

|类型 |描述|
|–|–|–|
|布尔型|布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 |
|数字类型 |整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。 |
|字符串类型|字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。 |
|派生类型|包括:指针类型(Pointer)、数组类型、结构化类型(struct)、Channel 类型、函数类型、切片类型、接口类型(interface)、Map 类型 |

2. 数字类型

Go 也有基于架构的类型,例如:int、uint 和 uintptr。

类型 描述
uint8 无符号 8 位整型 (0 到 255)
uint16 无符号 16 位整型 (0 到 65535)
uint32 无符号 32 位整型 (0 到 4294967295)
uint64 无符号 64 位整型 (0 到 18446744073709551615)
int8 有符号 8 位整型 (-128 到 127)
int16 有符号 16 位整型 (-32768 到 32767)
int32 有符号 32 位整型 (-2147483648 到 2147483647)
int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

3. 浮点型

类型 描述
float32 IEEE-754 32位浮点型数
float64 IEEE-754 64位浮点型数
complex64 32 位实数和虚数
complex128 64 位实数和虚数

带小数点的是浮点型,不带小数点的是整形

4. 其他数字类型

  • 以下列出了其他更多的数字类型:
类型 描述
byte 类似 uint8
rune 类似 int32
uint 32 或 64 位
int 与 uint 一样大小
uintptr 无符号整型,用于存放一个指针

四、Go 语言变量

  • 变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念,变量可以通过变量名访问

  • Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字

1. 变量声明

  • 声明变量的一般形式是使用 var 关键字
var identifier type

//可以一次声明多个变量:
var identifier1, identifier2 type
  • 实例
package main

import "fmt"

func main() {
	var a string = "hello"
	fmt.Println(a)

	var b, c int = 1, 2
	fmt.Println(b, c)
}

//输出结果如下
hello
1 2

2.变量声明方法

第一种,指定变量类型,如果没有初始化,则变量默认为零值

var v_name v_type
v_name = value
package main

import "fmt"

func main() {
	//声明一个变量并初始化
	var a = "goroute"
	fmt.Println(a)

	//没有初始化就为零
	var b int
	fmt.Println(b)

	//布尔值零值为false
	var c bool
	fmt.Println(c)
}


//输出的结果如下
goroute
0
false
数值类型(包括complex64/128)为 0

布尔类型为 false

字符串为 ""(空字符串)

第二种,根据值自行判定变量类型

var v_name = value
package main

import "fmt"

func main() {
	var a = true
	fmt.Println(a)
}

//输出结果如下
true

第三种,如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误

Go 语言基础语法_第3张图片

package main

import "fmt"

func main() {
	a := 1
	fmt.Println(a)
}

//此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
  • a := 1 相等于:
var a int 
a =1 
  • 可以将 var a string = “hello” 简写为 a := “hello”
package main

import "fmt"

func main() {
	//相当于var a string = "hello"
	a := "hello"
	fmt.Println(a)
}

3. 多变量声明

  • 类型相同多个变量, 非全局变量
package main

import "fmt"

func main() {
	a, b, c := 1, 2, 3
	fmt.Println(a, b, c)
}
  • 因式分解法
// 这种因式分解关键字的写法一般用于声明全局变量

var(
	test1 int
	test2 float32
	test3 string
)
  • 实例
package main

import "fmt"

var x, y int

var (
	a int
	b bool
)

var c, d int = 1, 2

var e, f = 666, "hello world!"

func main() {
	//这种不带声明格式的只能在函数体中出现
	g, h := 7878, "happy"
	fmt.Println(x, y, a, b, c, d, e, f, g, h)
}


//输出结果如下
0 0 0 false 1 2 666 hello world! 7878 happy

4. 值类型和引用类型

  • 所有像 intfloatboolstring 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值:

Go 语言基础语法_第4张图片

  • 当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝:

Go 语言基础语法_第5张图片

  • 可以通过 &i 来获取变量 i 的内存地址,例如:0xf840000040(每次的地址都可能不一样)

  • 值类型变量的值存储在堆中

  • 内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同

  • 更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存

  • 一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。

Go 语言基础语法_第6张图片

  • 这个内存地址称之为指针,这个指针实际上也被存在另外的某一个值中

  • 同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。

  • 当使用赋值语句 r2 = r1 时,只有引用(地址)被复制。

  • 如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响。

Go 语言基础语法_第7张图片

4.1 内存的压栈

压栈的顺序:先进后出
Go 语言基础语法_第8张图片

函数加入栈后,会执行赋值
Go 语言基础语法_第9张图片
Go 语言基础语法_第10张图片

弹栈:变量的释放

Go 语言基础语法_第11张图片

4.2 内存的堆

堆的顺序:先进先出

4.3 示例

package main

import "fmt"

//变量在内存中的存储方式

var num int = 10
var sun int = 20

func main() {

	var test1 = "hello"
	var test2 = "world"

	fmt.Println("num=", num)
	//调用内存地址使用&
	fmt.Println("num的内存地址是", &num)
	fmt.Println("sun的内存地址是", &sun)
	//调用函数中中变量
	fmt.Println(test1)
	fmt.Println(test2)
}


//输出结果如下
num= 10
num的内存地址是 0x709258
sun的内存地址是 0x709260
hello
world

上面代码中,在全局定义的变量是存放在栈中的,他是属于文件的

var num int = 10
var sun int = 20

而局部变量则是存放在堆中,是属于main函数的

	var test1 = "hello"
	var test2 = "world"

Go 语言基础语法_第12张图片

当全局变量加载完以后会加载main函数,但是main函数中定义的变量并不会被压栈,而是会被放入堆中
Go 语言基础语法_第13张图片

在test函数中是无法调用main函数中的变量的,存放位置是不同的
Go 语言基础语法_第14张图片

函数中的变量会随着函数的结束而结束它的生命周期

5. 变量的作用域

  • 在函数内部声明的变量教局部变量,生命周期仅限于函数内部

  • 在函数外部声明的变量交全局变量,生命周期作用于整个包,如果是大写首字母,则作用域整个程序

  • 语句块中的变量,生命周期仅限于语句块,语句块外部不能被识别

  • 示例

package main

import "fmt"

//定义全局变量
var a string = "10"

func main() {
	n()
	m()

	fmt.Println("主函数输出:", a)
}

func n() {
	println("n函数输出:", a)
}

func m() {
	a := "0"
	fmt.Println("m的函数输出:", a)
}


//输出结果如下
n函数输出: 10
m的函数输出: 0
主函数输出: 10

6. 简短形式,使用 := 赋值操作符

  • 查看变量的数据类型
package main

import "fmt"

/*
:=
定义即声明,无需写var,系统会自动推断数据类型,无需自定义数据类型
格式只能在函数体内
*/

func main() {
	num := "hello"
	fmt.Println(num)
	//查看变量的数据类型
	fmt.Printf("num的数据类型是:%T", num)
}

//输出结果为
hello
num的数据类型是:string

7. 空白标识符

  • 空白标识符_ 也被用于抛弃值,如值5_,b=5,7中被抛弃

  • _实际上是一个只写变量,你不能得到它的值,这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你不需要从一个函数得到所有返回值

  • 并行赋值也被用于当一个函数返回多个返回值时,比如这里的 val 和 错误 err 是通过调用Func1 函数同时得到:val,err = Func(var1)

package main

import "fmt"

func main() {
	_, numb, strs := numbers() //只获取函数返回值的后两个
	fmt.Println(numb, strs)
}

func numbers() (int, int, string) {
	a, b, c := 1, 2, "str"
	return a, b, c
}

//输出结果如下
2 str

五、常量

1. 什么是常量

  • 常量是一个简单值的标识符,使用 const 修饰,是程序在运行时,不会被修改的量

  • 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

  • 常量的定义格式:

const identifier [type] = value

//可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型

//显式类型定义: 
const b string = "abc"

//隐式类型定义: 
const b = "abc"

//多个相同类型的声明可以简写为:
const c_name1, c_name2 = value1, value2

2. 示例

package main

import "fmt"

func main() {
	const LENGTH int = 10
	const WIDTH int = 5
	var area int
	const a, b, c = 1, false, "str" //多重赋值

	area = LENGTH * WIDTH
	fmt.Printf("面积为 : %d", area)
	fmt.Println()
	fmt.Println(a, b, c)
}

//输出结果如下
面积为 : 50
1 false str
  • 常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:
package main

import (
	"fmt"
	"unsafe"
)

const (
	a = "abc"
	b = len(a)
	c = unsafe.Sizeof(a)
)

func main() {
	fmt.Println(a, b, c)
}

//输出结果如下
abc 3 16

3. iota

  • iota,特殊常量,可以认为是一个可以被编译器修改的常量。

  • iota 在 const 关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

  • iota 可以被用作枚举值:

const (
    a = iota
    b = iota
    c = iota
)

//第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;
//所以 a=0, b=1, c=2 可以简写为如下形式:

const (
    a = iota
    b
    c
)
  • 示例 ①
package main

import "fmt"

func main() {
	const (
		//iota相当于索引,从0开始
		a = iota //0
		b        //1
		c        //2
	)
	fmt.Println(a, b, c)
}

//输出结果
0 1 2
  • 示例 ②
//求半径为5的圆的面积和周长
//面积=Π*半径²
//周长=2*Π*半径

package main

import "fmt"

func main() {
	const Π float32 = 3.14
	var r float32 = 5
	//周长a
	a := 2 * Π * r
	//面积
	s := Π * r * r
	fmt.Println("周长:", a, "\n面积:", s)
}


//输出结果为
周长: 31.400002 
面积: 78.5
  • 案例 ③
//求出2的指数次方结果
package main

import "fmt"

func main() {
	const (
		a = 1 << iota //往左移0位
		b = 2 << iota //往左移1位
		c             //往左移2位
		d             //往左移3位
		e             //往左移4位
	)
	fmt.Println(a, b, c, d, e)
}

//输出结果如下
1 4 8 16 32
  • 案例 ④
//写一个程序获得当前运行系统中go的工作目录和项目目录路径,并输出在终端
package main

import (
	"fmt"
	"os"
)

func main() {
	//获取系统参数,go的工作目录
	var home string = os.Getenv("GOROOT")
	fmt.Println("go的工作目录是:", home)
	//获取go的项目目录
	var project string = os.Getenv("GOPATH")
	fmt.Println("go的项目目录是:", project)

}

//输出结果如下
go的工作目录是: D:\Go
go的项目目录是: D:\goproject
  • 案例 ⑥
//定义两个常量 Man=1 和 Female=2,获取当前时间的秒数,如果能被Female整除,则在终端打印Female,否则打印Man
package main

import (
	"fmt"
	"time"
)

const (
	Female = 2
	Man    = 1
)

func main() {
	for {
		//获取当前时间戳
		sec := time.Now().Unix()
		if sec%Female == 0 {
			fmt.Println("Female")
		} else {
			fmt.Println("Man")
		}
		//1000毫秒=1秒
		time.Sleep(1000 * time.Millisecond)
	}
}

你可能感兴趣的:(Golang,golang,开发语言,后端)