Go基本语法

一、package

  • package时最基本的分发单位和工程管理中依赖关系的体现;
  • 每个Go语言源代码文件开都都有一个package的声明,表示源码文件所属于代码包;
  • 要生成GO语言可执行程序,必须要有main的package包,且必须在该包下有main函数;
  • 同一个路径下只能存在一个package,一个package可以由多个源文件组成

二、import

import 只有一个功能,导入源代码依赖的package包,需要注意一下点:

  1. 不能导入源代码未用到的package包,否则go语言编译器会报错;
  2. 如果一个main包带入其它多个包,包将被顺序导入
    如果main包中导入的包(如A包)中又依赖了其它的包(如B包),会首先导入依赖的B包,然后初始化B包中的常量和变量,如果B包中还有init函数,会自动执行init函数,当main包中的所有包导入完后,才会对main包中的常量和变量进行初始化,然后执行main包中的init函数,最后执行main包中的main函数;
  3. 如果一个包被导入多次,则该包只被导入依次;

import 有如下两种写法
方式一:

import "package1"
import "package2"
import "package3"
……

方式二:

import(
	"package1"
	"package2"
	"package3"
	……
)

import 还有以下常用用法:
1、别名操作:将导入的包命名为另一个容易记忆的别名;

package main
import (
	mypackage "fmt"
)

func main()  {
	mypackage.Println("Hello World")
}

2、点(.)操作:通过点标识导入包后,调用该包中的函数时可以省略包前缀;

package main
import (
	. "fmt"
)

func main()  {
	Println("Hello World")
}

3、下划线(_)操作:用下划线导入的包,不导入整个包,而是执行包中的init函数,无法通过包名来调用包中的其他函数。使用下划线操作往往是为了注册包中的引擎,让外部方便调用。

package main
import (
	_ "fmt"
)

func main()  {
	fmt.Println("Hello World")
}

运行程序,报错,表示fmt未定义

# command-line-arguments
.\HelloWorld.go:7:2: undefined: fmt

三、数据类型

基本数据类型包括数值型、布尔型、字符串型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

变量被声明后的默认值情况:值类型的默认值为0,布尔型的默认值为false,String类型的默认值为空。

四、高级数据类型

1、数组类型
一个数组只能容纳若干相同类型的元素。

var arry1 [3]int 	//声明一个int类型的数组
arry1[0] = 0
arry1[1] = 1
arry1[2] = 2
var arry2 = [3]string{"a", "b", "c"} //声明并定义数组类型
var arry3 = [...]int{4, 5, 6}	//声明定义时,没有指定长度
var num int = len(arry3)	//求数组的长度

2、切片类型
切片类型与数组类型类似,可以容纳若干数据类型相同的元素,但切片类型不是定长度,切片类型可以通过数组进行切取

var arry1 = [6]int{1, 2, 3, 4, 5, 6}
var slice1  = arry1[1:3]
fmt.Println(len(slice1))	//2
fmt.Println(slice1)			//[2 3]

var slice2  = arry1[1:4:6]
fmt.Println(len(slice2))	//3
fmt.Println(slice2)			//[2 3 4]

var slice3  = append(slice2, 5, 6, 7)
fmt.Println(len(slice3))	//6
fmt.Println(slice3)			//[2 3 4 5 6 7]

var slice4 = []int{0, 0, 0, 0, 0, 0}
copy(slice4, slice2)
fmt.Println(len(slice4))	//6
fmt.Println(slice4)			//[2 3 4 0 0 0]

3、字典类型
字典类型用于存储键值对,同一个字典中的每个键都是唯一的。如果我们在向字典中放入一个键值对的时候其中已经有相同的键的话,那么与此键关联的那个值会被新值替换。

/*int键类型,string表示值类型*/
map1 := map[int]string{1:"a", 2:"b", 3:"c", 4:"d", 6:"f"}
/*6为键*/
value1 := map1[6]
fmt.Println(value1)		//f

map1[5] = "e"
value5, ok := map1[5]
fmt.Println(value5)		//e
fmt.Println(ok)			//true

/*删除键*/
delete(map1, 6)
fmt.Println(map1)		//map[1:a 2:b 3:c 4:d 5:e]

4、函数类型
go语言中函数由func关键字表示,在go语言中可以把函数赋给一个变量,通过变量来调用函数,例如 type myFunc my_func(s1 string, s2 string) string。常用形式如下:

package main

import "fmt"

func myfun(s1 string, s2 string) string {
	return  s1 + s2
}

func myfun1(s1 string, s2 string) (result string) {
	result = s1 + s2
	return  result
}

func myfun2(s1 string, s2 string) (int, string) {
	result := s1 + s2
	num := len(result)
	return num, result
}

func main()  {
	s := myfun("hello ", "world")
	fmt.Println(s)		//hello world

	s1 := myfun1("hello ", "china")
	fmt.Println(s1)		//hello china

	num, s2 := myfun2("hello ", "lzj")
	fmt.Println(num)	//9
	fmt.Println(s2)		//hello lzj
}

5、指针
go语言中指针表示形式与C语言中的类似,都是通过"*“获取地址中的值,通过”&"获取地址,用法如下:
用法一(同C写法):

package main

import "fmt"

type Person struct {
	name string
	age int
}

func increaseAge(num int, person *Person)  {
	(*person).age = (*person).age + num
}

func increaseAge2(num int, person Person)  {
	person.age = person.age + num
}

func main()  {
	var p1  *Person
	var p2  Person
	p1 = &Person{"lzj", 25}
	/*p1是一个指针,下面把该指针的副本传递给了increaseAge函数,
	p1的副本与p1同指向一个内存位置,所以p1的副本在increaseAge方法中修改了值,
	那么p1中的值也被修改了
	*/
	increaseAge(3, p1)	//方法中改变了p1的值
	fmt.Println((*p1).age)		//28

	/*p2是非指针类型的变量,下面把p2的值得副本传递给了increaseAge2函数
	p2的副本值改变了,但不影响p2的值,因为p2的副本仅是p2值得一个copy
	*/
	p2 = Person{"Bob", 20}
	increaseAge2(5, p2)	//方法未改变p2的值
	fmt.Println(p2.age)			//25
}

用法二:

package main

import "fmt"

type Person2 struct {
	name string
	age int
}

/*接受者类型是指针,称该方法为指针方法*/
func (person *Person2) increaseAge(num int){
	/*也可以写成person.age,会自动把person理解为指针的*/
	(*person).age = (*person).age + num
}

/*接受者类型为原型,称该方法为值方法*/
func (person Person2) increaseAge2(num int){
	person.age = person.age + num
}

func main()  {
	var p1 *Person2
	p1 = &Person2{"lzj", 25}
	p1.increaseAge(3)
	fmt.Println((*p1).age)

	var p2  Person2
	p2 = Person2{"Bob", 20}
	p2.increaseAge2(3)
	fmt.Println(p2.age)
}

6、interface
interface时一种类型,时拥有一组方法的类型,用type来定义。如果一个类型实现了interface中的所有方法,那么该类型是interface的一个实现类。interface类型可以没有方法,是一个empty interface,任何类型都是empty interface的实现类。

package main

import "fmt"

type I interface {
	Get() int
	Set(int)
}

type S struct {
	Age int
}

func(s S) Get()int {
	return s.Age
}

func(s *S) Set(age int) {
	s.Age = age
}

func f(i I){
	i.Set(10)
	fmt.Println(i.Get())	//输出10
}

func main() {
	s := S{}
	f(&s)
}

7、struct类型
Go语言中struct类型与C类似,但比C中的更灵活,可以为struct类型实现新的方法。

package main

import "fmt"

type Student struct {
	name string
	age int
}

/*可以为student类型添加方法*/
func (student *Student) increaseAge(num int) {
	(*student).age = (*student).age + num
}

func main()  {
	/*创建一个Student类型的值时,可以按顺序写,省略内部字段名*/
	student := Student{"lzj", 25}
	(&student).increaseAge(3)
	fmt.Println(student.age)		//28

	/*创建一个Student类型的值时,也可以选择不省略字段名*/
	student2 := Student{name:"Bob", age:20}
	(&student2).increaseAge(3)
	fmt.Println(student2.age)		//25
}

四、变量

全局变量的声明必须使用var关键词,局部变量可以省略;同一行可以声明多个变量。写法如下:

package main
import (
	"fmt"
)
/*变量声明赋值*/
var i1, i2, i3 int = 1, 2, 3
var(
	a string = "hello world"
	b int
)
func main()  {
	/*局部变量可以写成组的形式*/
	var(
		c uint = 10
		d string = "ddd"
	)
	/*局部变量可以省略var,全局的不可以省略*/
	e,f := 4,5
	……
}

变量类型转化
GO中不存在隐式转换,类型转换必须是显示的,并且只能发生在两种兼容类型之间,例如:

var i1 int = 1
var i4 float32 = float32(i1)

**注意:**大写字母开头的变量是可以导出的,也就是可以被其它包读取,是公用变量;
小写字母开头的是不可导出的,是私有变量。

五、常量

常量范围目前只支持布尔型、数字型、字符型。常量定义从形式上可以分为显示和隐式:
显示:const const_name1 type = value
隐式:const const_name2 = value

const MY_CONSTAT1 string  = "hello world"
const MY_XONSTANT2 = "HELLO CHINA"

const (
	MY_CONSTANT3 string ="hello go"
	MY_CONSTANT4  = "hello GO"
)

const language1,language2,language3 string = "go","java","python"

特殊常量iota的用法
iota在关键字const出现时被重置为0, const中每新增一行常量声明将使iota的计数加1。例如:

package main
import "fmt"

const a  = iota
/*b、c、d中只出现了一次const,所以b、c、d累加1*/
const(
	b = iota
	c = iota
	d = iota
)

func main()  {
	fmt.Println("a的值为:")
	fmt.Print(a)					/*a的值为0*/
	fmt.Print("\n")

	fmt.Println("b的值为:")
	fmt.Print(b)					/*b的值为0*/
	fmt.Print("\n")

	fmt.Println("c的值为:")
	fmt.Print(c)					/*c的值为1*/
	fmt.Print("\n")

	fmt.Println("d的值为:")
	fmt.Print(d)					/*d的值为2*/
	fmt.Print("\n")

iota的常见用法:
1、跳值使用法

package main
import "fmt"

const a  = iota
const(
	b = iota
	c = iota
	/*用_把2跳过去*/
	_ = iota
	d = iota
)

func main()  {
	fmt.Println("a的值为:")
	fmt.Print(a)					/*a的值为0*/
	fmt.Print("\n")

	fmt.Println("b的值为:")
	fmt.Print(b)					/*b的值为0*/
	fmt.Print("\n")

	fmt.Println("c的值为:")
	fmt.Print(c)					/*c的值为1*/
	fmt.Print("\n")

	fmt.Println("d的值为:")
	fmt.Print(d)					/*d的值为3*/
	fmt.Print("\n")
}

2、插队使用法

package main
import "fmt"

const(
	b = iota
	/*c插入b和d之间,b=0, d=2*/
	c = 5.12
	d = iota
)

func main()  {
	fmt.Println("b的值为:")
	fmt.Print(b)					/*b的值为0*/
	fmt.Print("\n")

	fmt.Println("c的值为:")
	fmt.Print(c)					/*c的值为5.12*/
	fmt.Print("\n")

	fmt.Println("d的值为:")
	fmt.Print(d)					/*d的值为2*/
	fmt.Print("\n")
}

3、表达式隐式使用法

package main
import "fmt"

const(
	b = iota * 2
	/*c和d隐式的继承iota * 2*/
	c
	d
)

func main()  {
	fmt.Println("b的值为:")
	fmt.Print(b)					/*b的值为0*/
	fmt.Print("\n")

	fmt.Println("c的值为:")
	fmt.Print(c)					/*c的值为2*/
	fmt.Print("\n")

	fmt.Println("d的值为:")
	fmt.Print(d)					/*d的值为4*/
	fmt.Print("\n")
}

4、单行使用法

package main
import "fmt"

const(
	/*iota在同一行不累加1,所以a=0, b=0+4=4*/
	a, b = iota, iota + 4
	/*c, d隐式继承a,b的格式,c=1, d=1+4=5*/
	c, d
	/*e等于2,注意e必须赋值,因为e不能隐式继承,因为格式不同*/
	e = iota
)

func main()  {
	fmt.Println("a的值为:")
	fmt.Print(a)					/*a的值为0*/
	fmt.Print("\n")

	fmt.Println("b的值为:")
	fmt.Print(b)					/*b的值为4*/
	fmt.Print("\n")

	fmt.Println("c的值为:")
	fmt.Print(c)					/*c的值为1*/
	fmt.Print("\n")

	fmt.Println("d的值为:")
	fmt.Print(d)					/*d的值为5*/
	fmt.Print("\n")

	fmt.Println("e的值为:")
	fmt.Print(e)					/*e的值为2*/
	fmt.Print("\n")
}

六、流程控制

1、if条件判断
示例一:

package main

import "fmt"

func main()  {
	var num  int = 10
	if num > 10{
		fmt.Println("num is bigger than 10")
	}else {
		fmt.Println("num is not bigger than 10")
	}
}

实例二:

package main

import "fmt"

func main()  {
	var num  int	//默认值为0
	if num := 20; num > 10{	//此地的num为if模块的局部变量,只在if模块使用,会覆盖全局的num值
		fmt.Println("num is bigger than 10")	//此地num值为20
	}else {
		fmt.Println("num is not bigger than 10")	//此地num值为20
	}
	fmt.Println("num 的值为:")
	fmt.Println(num)	//此地打印出的num为全局的num,值为0
}

2、switch条件语句
go语言的switch…case语句中,只要匹配到case中一条,就只执行该case,执行完就自动跳出,不像C语言需要在每个case执行完加break语句,否则会继续向下执行其它case语句。
示例一:

package main

import "fmt"

func main()  {
	var str string = "c"
	switch str {
	case "a":
		fmt.Println("str的值为a")
	case "b":
		fmt.Println("str的值为b")
	case "c":	//只执行该case
		fmt.Println("str的值为c")	//输出:str的值为c
	default:	//当没有一个case满足时,执行
		fmt.Println("str的值为其它")
	}
}

示例二:

package main

import "fmt"

func main()  {
	var str string = "c"	/*c为全局变量,值为c*/
	switch str := "b"; str { //局部变量str的值为b,会覆盖全局变量的c
	case "a":
		fmt.Println("str的值为a")
	case "b":
		fmt.Println("str的值为b")	//str的值为b
	case "c":
		fmt.Println("str的值为c")
	default:
		fmt.Println("str的值为其它")
	}
	fmt.Println(str)	//c 局部变量的值并不会改变全局的值,所以str的值依旧为c
}

示例三:case 说明符

package main

import "fmt"

func main()  {
	var num int = 10
	switch i := interface{}(num).(type){
	case int8 :
		fmt.Println(i)
		fmt.Println("num的类型为int8")
	case int16:
		fmt.Println(i)
		fmt.Println("num的类型为int16")
	case int32:
		fmt.Println(i)
		fmt.Println("num的类型为int32")
	case int64:
		fmt.Println(i)
		fmt.Println("num的类型为64")
	case int:
		fmt.Println(i)	//10
		fmt.Println("num的类型为int")	//num的类型为int
	default:
		fmt.Println("num其它类型")
	}
}

3、for语句
示例1:循环输出

package main

import "fmt"

func main()  {
	for i := 0; i < 5; i++ {
		fmt.Println(i)
	}
}

示例二:for语句中用range
range每次迭代都会返回两个值,一个是索引,一个索引处所代表的值

package main
import "fmt"

func main()  {
	var str string = "GO语言"
	for i,c := range str{
		fmt.Printf("%d : %c\n", i, c)
	}
}

输出:

0 : G
1 : O
2 : 语
5 : 言

因为go语言中所有字符和汉字都是用utf-8进行编码的,一个汉字占3个字节,range返回的“语”和“言”都是第一个字节作为索引。

range可以迭代字符串类型,数组类型,数组的指针类型,切片类型,字典类型,通道类型。
对于字符串类型,数组类型,数组的指针类型,切片类型,range每次迭代出两个值,第一个代表迭代处的索引,第二个值代表迭代处的值;
对于字典类型,range每次也迭代出两个值,第一个代表键,第二个代表键对应的内容,注意迭代不能保证顺序;
for语块中可以用break或continue,用法通C语言。

七、异常处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制,error类型是一个接口类型,这是它的定义:

type error interface {
    Error() string
}

在实际应用中,可以抛出系统的异常,也可以抛出指定的异常,示例如下:

package main

import (
	"errors"
	"fmt"
	"os"
)

func isFileExist(path string) (bool, error) {
	if path == "" {
		return false, errors.New("传入路径为空")		//返回自定义的错误
	}
	_, err := os.Stat(path)
	if err != nil {
		return true, err							//返回系统的错误
	}
	return false, errors.New("未知的错误")			//返回自定义的错误
}

func main()  {
	path := ""
	flag, err := isFileExist(path)
	fmt.Println(flag)			//输出:false
	fmt.Println(err.Error())	//输出:传入路径为空
}

也可以自己实现Error接口,并自定义错误,示例如下:

package main

import "fmt"

type My struct {
	age int
}

func (my *My) Error() string {
	str := `除数不能为0: %d / 0`
	return fmt.Sprintf(str,(*my).age)
}

func divideError(my1 *My, my2 *My) (result int, erroMsg string) {
	if my2.age == 0 {
		return 0, my1.Error()
	}else {
		return my1.age / my2.age, ""
	}
}

func main()  {
	var my1 *My
	var my2 *My
	my1 = &My{25}
	my2 = &My{0}
	num, err := divideError(my1, my2)
	fmt.Println(num)		//输出:0
	fmt.Println(err)		//输出:除数不能为0: 25 / 0
}

注意:比如my1是struct类型的指针,调用内部元素时,可以通过(*my1).age,也可以通过my1.age,因为go会自动进行类型推断

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于上面的引用内容,golang的基础语法学习可以参考以下几个步骤: 1. 首先,我们需要安装golang的开发环境。你可以直接进入官网(https://go.dev/)下载并安装golang的解释器。 2. 接下来,我们可以开始学习golang的语法。从上面的引用内容可以看出,golang的语法和Java的结构很相似,所以如果你之前有Java编程的经验,可以借鉴一些类比来学习。但是即使你没有Java的经验,也不用担心,golang的语法相对简单并且易于学习。 3. 另外,golang被称为“云计算时代的开发利器”,在使用过程中给人一种优雅、亲切、舒适的感觉。因此,在学习golang的过程中,你可能会发现它的语法设计和使用方式非常人性化。 综上所述,学习golang的基础语法可以通过安装开发环境、参考Java的结构以及体验其优雅、亲切、舒适的特点来进行。希望这些信息能够帮助你开始学习golang的基础语法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [一文看完golang基础语法](https://blog.csdn.net/qq_35889508/article/details/128125279)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值