Go 语言快速开发入门(基础语法详解,第一节)

本文详细介绍了Go语言的基础语法。涵盖HelloWorld代码编写与注意事项,转义字符和注释的使用,变量与常量的声明方式,基本和复杂数据类型,值类型与引用类型的区别,各类运算符,if和switch流程控制,以及函数和包的相关知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础语法详解,第一节

1、HelloWorld

1.1、代码编写和解释

代码如下,对下图代码进行解释:
1、代码中的package main,表示这是可以执行main方法的文件,如果Test.go文件不放在main目录下,也可以写成package main,不过通常是放在main包中。
2、import “fmt” 表示引入一个包,包名 fmt, 引入该包后,就可以使用 fmt 包的函数,比如:fmt.Println。
3、func main() {} 表示一个main方法,类似java中的main方法,是go的入口。
4、fmt.Println(“hello,world”) 表示调用Println输出。
在这里插入图片描述
5、程序运行,如下图,右键单击即可运行。
在这里插入图片描述

1.2、go语言注意事项

  • Go 源文件以 “go” 为扩展名。
  • Go 应用程序的执行入口是 main()函数,但是main函数的所在包必须是package main。
  • Go 语言严格区分大小写。
  • Go 方法由一条条语句构成,每个语句后不需要分号(Go 语言会在每行后自动加分号),这也体现出 Golang 的简洁性。也就是说go的一行只能写一句代码。
  • go 语言定义的变量或者 import 的包如果没有使用到,代码不能编译通过且开发工具会自定删除掉。
  • 大括号都是成对出现的,缺一不可。且面朝右面的大括号左边必须有代码。

2、Go 语言的转义字符&&Go 语言注释

2.1、常用制表符

  • \t : 表示一个制表符,通常使用它可以排版。
  • \n :换行符
  • \\ :一个\
  • \" :一个"
  • \r :一个回车 fmt.Println(“a\rb”);

2.2、注释

Golang 中注释有两种形式
1、行注释
//注释内容
2、块注释(多行注释)
/*
注释内容
*/

下图代码举例

func main() {
	//一个制表符的距离
	fmt.Println("刘备\t猴子")
	//换行
	fmt.Println("姜子牙\n高端局")
	//\r回车, \r后面的覆盖掉前面的
	fmt.Println("王者荣耀\r英雄联盟")
	/*
	  这是多行注释
	  这是多行注释
	*/
}

3、变量

3.1、变量声明方式

import "fmt"

/**
变量声明和使用
*/

//变量声明六:一次声明多个全局变量(方法外的变量是全局变量)
var (
	n3    = 100
	n4    = 400
	name3 = "zg"
)
//一次声明一个全局变量
var name4 = "zgg"

func main() {
	//变量声明方式一,如果不指定变量值,则使用默认值
	var i int
	i = 90
	fmt.Println(i)

	//变量声明方式二:根据值自行判定变量类型(类型推导)
	var age = 20
	fmt.Println(age)
	//变量声明方式三:省略 var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误,只能在当前函数作用域中使用,不能作为全局变量
	name := "zhanggang"
	fmt.Println(name)
	//变量声明方式四: var 变量名 类型 = 表达式
	var name2 string = "zhanggang"
	fmt.Println(name2)
	//变量声明方式五:一次声明多个变量
	n1, n2, vmId := 1, 2, "fe7772b4-8dfc-4b23-8916-616d79c53b31"
	fmt.Println(n1, n2, vmId)

	fmt.Println(n3, n4, name3, name4)
}

3.2、常量声明方式

常量的定义: 相对于变量,常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。常量的声明和变量声明非常类似,只是把 var 换成了 const,常量在定义的时候必须赋值。

func main() {
	//声明单个常量
	const pi1 = 3.1415
	//声明多个常量
	const (
		pi2 = 3.1415
		e   = 2.7182
	)
	//const 同时声明多个常量时,如果省略了值则表示和上面一行的值相同,N1=N2=N3=100
	const (
		N1 = 100
		N2
		N3
	)
}

4、基本数据类型

Go 语言中数据类型分为: 基本数据类型和复合数据类型。
基本数据类型有: 整型、浮点型、布尔型、字符串
复杂数据类型有: 指针、数组、切片、结构体、函数、map、通道(channel)、接口等。

4.1、整型

1、整型分为以下两个大类
有符号整形按长度分为:int8、int16、int32、int64
对应的无符号整型:uint8、uint16、uint32、uint64
特殊整型:int
2、特殊整型
注意: 在使用 int 和 uint 类型时,不能假定它是 32 位或 64 位的整型,而是考虑int 和uint
可能在不同平台上的差异。在涉及到二进制传输、为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用 int 和 uint。
在这里插入图片描述
3、代码演示

import (
	"fmt"
	"unsafe"
)

/**
基本数据类型
*/
func main() {
	//整数类型
	var num = 123
	fmt.Printf("值:%v 类型%T  ", num, num)
	//返回 num 变量占用的字节数
	fmt.Println(unsafe.Sizeof(num))
}

4.2、浮点型

注意:
1、Go 语言支持两种浮点型数:float32 和 float64。
2、Go 语言中浮点数默认是 float64。
3、Golang 中 float 精度丢失,几乎所有的编程语言都有精度丢失这个问题,这是典型的二进制浮点数精度损失问题,在定长条件下,二进制小数和十进制小数互转可能有精度丢失。

在这里插入图片描述

代码演示

func main() {
	num := 1.1
	//Go 语言中浮点数默认是 float64
	fmt.Printf("值:%v--类型:%T", num, num) //值:1.1--类型:float64

	m1 := 8.2
	m2 := 3.8
	fmt.Println(m1 - m2) // 期望是 4.4,结果打印出了 4.399999999999999,这就是丢失精度

	//Golang 科学计数法表示浮点类型
	num8 := 5.1234e2   // ? 5.1234 * 10 的 2 次方
	num9 := 5.1234e2   // ? 5.1234 * 10 的 2 次方 shift+alt+向下的箭头
	num10 := 5.1234e-2 // ? 5.1234 / 10 的 2 次方 0.051234
	fmt.Println("num8=", num8, "num9=", num9, "num10=", num10)
}

4.3、布尔值

Go 语言中以 bool 类型进行声明布尔型数据,布尔型数据只有 true(真)和false(假)两个值。
注意:

  1. 布尔类型变量的默认值为 false。
  2. Go 语言中不允许将整型强制转换为布尔型.
  3. 布尔型无法参与数值运算,也无法与其他类型进行转换。
import ( "fmt"
"unsafe"
)
func main() {
var b = true
fmt.Println(b, "占用字节:", unsafe.Sizeof(b))
}

4.4、字符串

注意: Go 语言中的字符串属于基础数据类型。

声明字符串代码演示

func main() {
	//声明一个字符串变量
	s1 := "hello"
	//多行字符串,就是一个很长的字符串,需要换行,必须使用反引号字符
	//反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。
	s2 := `你好
漂亮的go语言`
	fmt.Println(s1, s2)
}

在这里插入图片描述

字符串API常用方法

func main() {
	//len(str)求字符串的长度
	var str = "this is str"
	fmt.Println(len(str))

	//拼接字符串
	var str1 = "你好"
	var str2 = "golang"
	fmt.Println(str1 + str2)
	var str3 = fmt.Sprintf("%v %v", str1, str2)
	fmt.Println(str3)

	//strings.Split 分割字符串
	var strSpi = "123-456-789"
	var arr = strings.Split(strSpi, "-")
	fmt.Println(arr)

	//判断一个字符串是否包含另一个字符串
	var str4 = "this is golang"
	var flag = strings.Contains(str4, "golang")
	fmt.Println(flag)

	//判断首字符尾字母是否包含指定字符
	var str5 = "this is golang"
	var flag2 = strings.HasPrefix(str5, "this")
	fmt.Println(flag2)
}

4.5、基本数据类型默认值

在这里插入图片描述

代码演示

func main() {
	var a int
	var b float64
	var c bool
	var d string
	fmt.Println(a, b, c, d)
}

5、复杂数据类型

复杂数据类型有: 指针、数组、切片、结构体、函数、map、通道(channel)、接口等。

5.1、指针

注意:
1、对于基本数据类型来说,变量存的就是值,也叫值类型,而指针就是指向值的一个地址。 举例说明下,var num int = 999,内存中会有两块地方存储,一块存储值10,另一块存储值10的内存地址。通过&num可以获取num的内存地址,var ptr *int = &num 这就是声明一个指向num内存的指针。
2、*int表示这个指针的类型
3、值类型都有对应的引用类型,

值类型包括:基本数据类型 int 系列, float 系列, bool, string 、数组和结构体struct
引用类型:指针、slice 切片、map、管道 chan、interface 等都是引用类型

代码演示

func main() {
	var i int = 999
	fmt.Println("i的地址是=", &i)
	//*int表示这个指针的类型
	var ptr *int = &i
	fmt.Printf("ptr=%v\n", ptr)
	fmt.Printf("ptr的地址是=%v\n", &ptr)
	fmt.Printf("ptr指向的值是=%v", *ptr)
}

下图的指针在内存中的指向
在这里插入图片描述

一个小案列,通过指针修改变量的值

func main() {
	var i int = 999
	fmt.Println("i的值是=", i)
	var ptr *int = &i
	*ptr = 100  //在内存中,*ptr指向的值就是i的,所以能修改i的值
	fmt.Println("i的值是=", i)
}

5.2、数组

5.2.1、一维数组

数组定义: var 数组变量名 [元素数量]T

定义一个长度为 3 元素类型为 int 的数组 b 并赋值。

	var b [3]int
	b[0] = 80
	b[1] = 100
	b[2] = 96
	//根据数组下表获取值
	fmt.Println(b[0])

数组的初始化 方法一

var testArray [3]int                        //数组会初始化为int 类型的零值var
var numArray = [3]int{1, 2}                 //使用指定的初始值完成初始化
var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
fmt.Println(testArray)                      //[0 0 0]
fmt.Println(numArray)                       //[1 2 0]
fmt.Println(cityArray)   					//[北京 上海 深圳]

数组的初始化 方法二
按照方法一的方法每次都要确保提供的初始值和数组长度一致,一般情况下我们可以让编译器根据初始值的个数自行推断数组的长度。

var testArray [3]int
var numArray = [...]int{1, 2}
var cityArray = [...]string{"北京", "上海", "深圳"}
fmt.Println(testArray)                          //[0 0 0]
fmt.Println(numArray)                           //[1 2]
fmt.Printf("type of numArray:%T\n", numArray)   //type of numArray:[2]int
fmt.Println(cityArray)                          //[北京 上海 深圳]
fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string

数组的初始化 方法三
使用下标索引初始化

a := [...]int{1: 1, 3: 5}
	fmt.Println(a)                  // [0 1 0 5]
	fmt.Printf("type of a:%T\n", a) //type of a:[4]int

遍历数组的两种写法

var a = [...]string{"北京", "上海", "深圳"}
	// 遍历 1:for 循环遍历
	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}
	// 遍历 2:range 循环遍历
	for index, value := range a {
		fmt.Println(index, value)
	}
5.2.2、二维数组

var 数组变量名 [元素数量][元素数量]T

二维数组定义

func main() {
	a := [3][2]string{
		{"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}}
	fmt.Println(a)       //[[北京 上海] [广州 深圳] [成都 重庆]]
	fmt.Println(a[2][1]) //支持索引取值:重庆
}

二维数组遍历

func main() {
	a := [3][2]string{
		{"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}}
	for _, v1 := range a {
		for _, v2 := range v1 {
			fmt.Printf("%s\t", v2)
		}
		fmt.Println()
	}
}

注意:
1、Go 语言是支持多维数组的,我们这里是以二维数组为例。
2、多维数组只有第一层可以使用…来让编译器推导数组长度。
3、数组是值类型,传参相当于值拷贝,不改变原有的值。

5.3、切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。
因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性,所以我们才有了切片。

举例说明数组的权限性:

func main() {
	a := [4]int{1, 2, 3, 4}
	println(arraySum(a))
	//b := [5]int{1, 2, 3, 4, 5}
	//println(arraySum(b)) //错误,函数只能接受[4]int 类型,其他的都不支持。所以传入长度为5 的数组的时候就会报错。
}

func arraySum(x [4]int) int {
	sum := 0
	for _, v := range x {
		sum = sum + v
	}
	return sum
}

切片定义

var name []T
name是变量名称
T是表示切片中的元素类型

注意: nil相等于java中的null, 当你声明了一个变量 , 但却还并没有赋值时 , go 会自动给你的变量赋值一个默认零值。这是每种类型对应的默认值,基本类型有自己对应的默认值,复杂类型默认都是nil

func main() {
	// 声明切片类型
	var a []string              //声明一个字符串切片
	var b = []int{}             //声明一个整型切片并初始化
	var c = []bool{false, true} //声明一个布尔切片并初始化
	var d = []bool{false, true} //声明一个布尔切片并初始化

	fmt.Println(a) //[]
	fmt.Println(b) //[]
	fmt.Println(c) //[false true]

	fmt.Println(a == nil) //true
	fmt.Println(b == nil) //false
	fmt.Println(c == nil) //false
	fmt.Println(c == d)   //报错,切片是引用类型,不支持直接比较,只能和nil 比较
}

切片的循环遍历

func main() {
	var a = []string{"北京", "上海", "深圳"}
	// 方法 1:for 循环遍历
	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}

	// 方法 2:for range 遍历
	for index, value := range a {
		fmt.Println(index, value)
	}
}

6、值类型和引用类型

值类型包括: 基本数据类型 int 系列, float 系列, bool, string 、数组和结构体struct。
引用类型: 指针、slice 切片、map、管道 chan、interface 等都是引用类型。

值类型概念:
变量直接存储值,内存通常在栈中分配。
在这里插入图片描述

引用类型概念:
变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收。
在这里插入图片描述

7、运算符

7.1算术运算符

就是简单的加减乘除,下面是计算范例,这里就不用代码演示了
在这里插入图片描述

7.2关系运算符

在这里插入图片描述

7.3逻辑运算符

注意:
&&也叫短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为false。
||也叫短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为true。
在这里插入图片描述

7.4 赋值运算符

在这里插入图片描述

8、流程控制

8.1、if流程

代码演示

func main() {
	age := 30
	if age > 30 {
		fmt.Println("大于30")
	} else if age == 30 {
		fmt.Println("等于30")
	} else {
		fmt.Println("小于30")
	}
}

8.2、switch流程

9、函数和包

9.1函数

拥有一个返回值的函数

func main() {
	n1 := 1
	n2 := 2
	//计算n1+n2并返回值
	result := cal1(n1, n2)
	fmt.Println(result)
}

func cal1(n1 int, n2 int) int {
	i := n1 + n2
	return i
}

拥有两个返回值的函数

func main() {
	n1 := 1
	n2 := 2
	/**
	计算n1+n2并返回值
	判断n1是否大于n2
	*/
	result, flag := cal2(n1, n2)
	fmt.Println(result, flag)
}

func cal2(n1 int, n2 int) (int, bool) {
	i := n1 + n2
	return i, n1 > n2
}

有参数没返回值

func main() {
	cal("hello,函数")
}

func cal(str string) {
	fmt.Println("cal函数被调用了", str)
}

没参数没返回值

func main() {
	cal3()
}

func cal3() {
	fmt.Println("cal函数被调用了")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂IT民工_程序员_ZG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值