Go语言(基础语法学习)

Go:简单语法介绍

学习(1)运算符

Go:运算符学习
添加新的运算符
对于++,- -也有新的要求
返回值
指针的运算规则
/------------------------------------------------------------------------------

学习(2)数组与切片

Go:切片与数组学习

数组的定义方法
切片的定义方法
数组和切片的对比及其使用

一、字符串尾部不包含NULL字符,与c/c++不一样

二、字符串是常量,可以访问字节单元但是不能修改某个字节单元的值;基于字符串创建的切片和原字符串指向相同的底层字符数组,一样不能修改

package main

import "fmt"

func main(){
	s := "Hello World"
	s[2] = 's'		//error
	a := s[:3]
	fmt.Print(s,"\n",a)
	a[2] = 's' 		//error
}

三、字符串和切片的转换

package main

import "fmt"

func main(){
	s := "Hello World"
	//字符串可以转换为字节数组,也可以转换为Unicode的字符数组
	a0 := []rune(s)			//[72 101 108 108 111 32 87 111 114 108 100]
	a1 := []byte(s)			//[72 101 108 108 111 32 87 111 114 108 100]
	fmt.Print(a0,"\n",a1)
}

四、数组初始化

	a := [3]int{1,2,3}		//初始化长度和字面量 [1 2 3]
	a := [...]int{1,2,3}	//根据输入的数据个数确定长度 [1 2 3]
	a := [3]int{1:1, 2:3}	//指定总长度,通过索引值进行初始化,未初始化的元素使用类型默认值 [0 1 3]
	a := [...]int{1:1, 2:3} //不指定总长度,通过索引值初始化,长度由最后一个索引值确定,
							//未指定索引的元素被初始化为类型的零值 [0 1 3]

数组特点:

  1. 数组创建完长度就固定了,不可以再追加元素
  2. 数组是**值类型的 **,数组赋值或作为函数参数都是值拷贝
  3. 数组的长度是数组类型的组成部分
    [10]int 和 [20]int表示不同数组
  4. 可以根据数组创建切片

五、切片初始化
切片的内部

	a := [5]int{1, 2, 3, 4, 5} //[1 2 3 4 5]
	sl := a[1:] 			   //通过数组创建;[2 3 4 5]
	
	s2 := make([]int,5)		   //使用 make创建,len == cap = 5;  [0 0 0 0 0]

	var s3 []int			   //这是无意义的; []

/------------------------------------------------------------------------------

学习(3)map与结构体

Go:map与结构体学习

一、map的定义与创建
与切片一样,未创建的map是不能使用的)

	//根据字面量创建
	a := map[string]int{"a":1,"b":2}
	fmt.Println(a)		//map[a:1 b:2]
	fmt.Println(a["a"])	//1

	//使用 make 创建
	b := make(map[string]string)	//长度为默认值0
	b2 :=make(map[string]string,10) //长度为 10
	b3 := make(map[int]int)
	b["name"] = "Tom"				//增加元素后长度逐渐增加
	b2["name"] = "John"
	b2["sex"] = "M"
	fmt.Println(b,len(b)) 								//map[name:Tom] ,len = 1
	fmt.Println(b2["name"],b2["sex"],len(b2))			//John M ,len = 2
	fmt.Println(b3,len(b3))								//map[], len = 0

map的增、删、改、查、遍历(无序)

二、结构体的定义与创建
与切片和map不一样,定义了的结构体即可使用其变量)

//自定义结构体类型,并初始化
package main

import (
	"fmt"
)

func main() {
	type Person struct {
		name string
		age int
		sex string		//增加字段sex
	}
	//不推荐
	a := Person{"Tom",1}	//报错,因为没有初始化sex
	fmt.Println(a)
	//推荐
	a :=&Person{
		name: "Tom",
		age:  0,	
		//未初始化的字段(sex)会被默认值初始化
	}
	fmt.Println(*a)		//{Tom 0 }
}

结构体类型转换规则
匿名属性(结构体类型的匿名属性,及其访问规则

/------------------------------------------------------------------------------

学习(4)函数

Go:函数学习

一、函数的特点

  1. 函数可以没有输入参数,也可以没有返回值
  2. 多个相邻的相同类型的参数可以使用简写模式
    例如
func fun(a,b int,f float32){}
  1. 支持有名的返回值,最后return可以不带参数名直接返回
func fun(a,b int)(sum int){
	sum = a + b
	return //return sum 的简写形式
	------------------------------
	sum := a + b	//如果是这样,则相当于新声明一个sum变量,将返回变量sum覆盖
	return sum 		//最后要显式调用 return sum
}
  1. 不支持默认值参数
  2. 不支持函数重载
  3. 不支持函数嵌套,严格说是不支持命名函数的嵌套定义,但支持嵌套匿名函数,例如
//正确,使用了匿名函数嵌套
func add(a,b int)(sum int){
	anonymous := func(x,y int)int{
		return x + y
	}
	return anonymous(a, b)
}

//错误
func add(a,b int)(sum int){
	 func(x,y int)int{//写成func add2(x,y int)int 也是错误的
		return x + y
	}
	return anonymous(a, b)
}

二、多值返回
定义多值返回时的返回参数列表要使用“()”包裹,并支持命名参数返回

func swap(a, b int)(int int){
	return b ,a
}

三、不定参数
特点:

  1. 所有不定参数的类型必须是相同的
  2. 不定参数必须是函数的最后一个参数
  3. 不定参数名在函数体内相当于切片,对切片的操作同样适合对不定参数的操作
  4. 切片可以作为参数传递给不定参数,切片名后要加上“…"
package main

import "fmt"

func Sum(arr...int)(sum int){
	for _,value:=range arr{	//此时arr就相当于切片,可以使用range访问
		sum += value
	}
	return sum
}
func main(){
	fmt.Println(Sum(1,2,3))	//6

	a := [...]int{1,2,3,4}
	slics := a[:]
	fmt.Println(Sum(slics...))		//10
	
	fmt.Println(Sum(a))		//error,数组不可以作为实参传递给不定参数函数中的参数
}
  1. 形参为不定参数的函数 和 形参为切片的函数类型不同
package main

import "fmt"

func suma(arr...int)(sum int){
	for _,v:=range arr{
		sum += v
	}
	return
}
func sumb(arr []int)(sum int){
	for _,v:=range arr{
		sum += v
	}
	return
}

func main(){
	//suma 和 sumb 类型并不一样
	fmt.Printf("%T\n",suma)	//func(...int) int
	fmt.Printf("%T\n",sumb)	//func([]int) int
}

四、函数签名

  1. 函数类型又叫做函数签名,一个函数的类型就是函数定义首行去掉函数名、参数名和{,可以使用fmt.Printf的%T格式化参数打印函数类型,例如上面的代码
  2. 两个函数类型相同的条件是:拥有相同的形参列表和返回值列表(列表元素的次序、个数和类型都相同),形参名可以不同,例如
//两个函数类型相同
func add(a, b int)int{return a+b}
func Sum(x int, y int)(sum int){
	sum = x+y
	return 
}
  1. 可以使用type 定义函数类型,函数类型变量可以作为函数的参数或返回值
package main

import "fmt"

func suma(arr...int)(sum int){
	for _,v:=range arr{
		sum += v
	}
	return
}
type op func(...int)int

func Hanshu(f op)int{
	return f(1,2,3)
}
func main(){
	fmt.Println(Hanshu(suma))	//6
}

五、匿名函数
匿名函数可以看作函数字面量,所有直接使用函数类型变量的地方都可以由匿名函数代替。

  1. 可以直接赋值给函数变量
package main

import (
	"fmt"
)

func main()  {
	var f = func()int{
		return 1
	}
	fmt.Printf("%T\n",f)	//func() int
	fmt.Println(f())	//1
}
  1. 可以当作实参
package main

import "fmt"

type op func(int)

func Prints(f op){
	fmt.Printf("%T",f)
}
func main(){
	Prints(func(i int) {})	//main.op
}
  1. 可以作为返回值
//典型例子斐波那契数列(使用闭包)
func Fib()func()int{
	a:=-1
	b:=1
	return func()int{
		a,b = b,a+b
		return b
	}
}
  1. 可以直接调用
package main

import "fmt"

func main(){
	fmt.Printf("%T",func(int){})	//func(int)
}

六、闭包

对象是附有行为的数据,而闭包是附有数据的行为

概念:闭包是由函数及其相关引用环境组合而成的实体,一般通过在匿名函数中引用外部函数的局部变量或包全局变量构成
闭包 = 函数 + 引用环境
如果函数返回的闭包引用了该函数的局部变量(参数或函数内部变量):

  1. 多次调用该函数,返回的多个闭包所引用的外部变量是多个副本,原因是每次调用函数都会为局部变量分配内存
  2. 用一个闭包函数多次,如果该闭包修改了其引用的外部变量,则每次调用该闭包对该外部变量都有影响,因为闭包函数共享外部引用
  3. 如果闭包调用的是全局变量,则每次调用该闭包都会对全局变量产生影响,所以闭包引用全局变量并不是一个好的编程方式
//1.调用参数的闭包
package main

import "fmt"

func fa(n int) func() {
	n++
	return func() {		//注意,这里闭包调用的是参数n,而没有调用函数内部变量,
						//所以n++ 并不起作用,且由于闭包内未对n做处理,输出时就按原值输出
		fmt.Println(n)
	}
}
func fb(n int)func(){
	return func(){		//这里闭包调用了参数且对其做了++处理
		n++
		fmt.Println(n)
	}
}
func main(){
	a := fa(1)
	a()			//2
	a()			//2
	fmt.Println()
	b := fb(1)
	b()			//2
	b()			//3
}
//2.调用函数内部变量的闭包
package main

func Sum()func()int{
	a := 0
	f := func()int {
		a++
		return a
	}
	return f
}
func main()  {
	a0 := Sum()
	println(a0())	//1
	println(a0())	//2
}

内函数对外函数的变量的修改,是对变量的引用

引用链接:对闭包理解有帮助

对其理解--------------------------------------------------------------------/
将拥有闭包的函数称为背包;
从背包外拿东西(传入参数),在背包内处理(利用闭包处理参数),
从背包内拿东西(函数内部变量),在背包内处理(利用闭包处理内部变量)

/------------------------------------------------------------------------------

学习(5)
指针的定义和使用规则
指向切片的指针(二级指针)
指针作为返回值的规则
Go:指针学习

学习(6)
面向对象,使用
“方法”进行绑定 +
组合(在c++中的继承)+
代码首字母的大小写

----------->进行封装
继承方式及规则和c++很像只是语法不同,包括继承的函数的重写…
Go:面向对象简单学习

一、指针接受者的方法
该知识点在于绑定方法时,实参接收者和形参接收者的选择
1.

package main

import "fmt"

type S struct {
	x,y int
}
func (s S)Sum()int{		//形参接收者为 S 类型
	return s.x+s.y
}
func main(){
	fmt.Println(S{1,2}.Sum())	//实参接收者也为 S 类型
}

2.

package main

import "fmt"

type S struct {
	x,y int
}
func (s *S)Sum()int{		//形参接收者为 *S 类型
	return s.x+s.y
}
func main(){
	t := &S{1,2}
	fmt.Println(t.Sum())	//实参接收者也为 *S 类型
}

3.

package main

import "fmt"

type S struct {
	x,y int
}
func (s *S)Sum()int{		//形参接收者为 *S 类型
	return s.x+s.y
}
func main(){
	var t = S{1,2}
	fmt.Println(t.Sum())	//实参接收者为 S 类型
							//此时 t 会被隐式转换为 &t
}

4.

package main

import "fmt"

type S struct {
	x,y int
}
func (s S)Sum()int{		//形参接收者为 S 类型
	return s.x+s.y
}
func main(){
	var t = &S{1,2}
	fmt.Println(t.Sum())	//实参接收者为 *S 类型
							//此时 t 会被隐式转换为 *t
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值