Go语言学习--避免入坑版

   本博文主要整理一些Go语言的特点,适宜于有go语法基础的同学,帮助大家一起扫盲golang,如需转载请联系作者

1.++,--

golang语法中,只有a++;a--;    不存在--a;++a语法

 

2.String

1. Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。
而Java中String不属于基本数据类型

2. 通过下标直接获取字符串中某个元素的值
例如:s:="abc"  //s[0]=a

 

3.boolean

Go 语言中不允许将整型强制转换为布尔型.

布尔型无法参与数值运算,也无法与其他类型进行转换。
例如java执行下面的语句可以编译通过
if(1){System.out.println("条件为真")}
但是Golang执行对应的语句报错,错误信息为//non-bool 0 (type int) used as if condition
if(1){fmt.Println("条件为真")}

 4.defer

defer 延迟调用
如果存在多个defer是,按照先进后出的顺序执行

5.数组比较

golang提供了数组比较的原生方法

num1 := [5]int{2, 2, 3, 4, 5}
num2 := [5]int{1, 2, 3, 4, 5}
num1 == num2 //相等为true,不相等为false
num1 != num2

6.切片

大家在学其他强类型编程语言时,多么渴望数组能够动态变化。Go语言中,就有切片可以解决,让您使用起来随心所欲;
切片,是解决数组的长度无法变化的利器,切片可进行拼接,长度自由等好处;
切片的本质是就是结构体

7.类型转换(特殊)

// 平常我们常见的类型转换格式:(类型)变量 ,int a; (float)a
// golang还有另外一种类型转换方式
userLogin, _ := bc.Get("user") // userLogin的类型:interface{}
u := userLogin.(*services.User) // 将userLogin 强转为User类型

8.结构体打印(类似java的toString()方法)

打印 Go 结构体(struct)信息:fmt.Printf("%+v", user)

代码:
package main
 
import "fmt"
 
// 用户
type User struct {
    Id   int
    Name string
    Age  int
}
 
func main() {
    user := User{Id:2, Name:"golang"}
 
    // 打印 结构体
    fmt.Printf("%+v", user)
 
    // 输出换行符
    fmt.Printf("\n")
 
    // 判断实例是否为空
    fmt.Println(user == User{})
}


输出:
{Id:2 Name:golang Age:0}
false

 

9.golang提供的MD5加密方法

https://studygolang.com/articles/2283

 

10.interface{}与struct

interface 针对方法的定义
struct 针对普通的数据结构定义

深入了解:https://www.cnblogs.com/zhangdewang/p/10612089.html

 

11.切片传参、map传参时原值会被修改,而结构体、普通数组传参时原值不会被改变。

     形参所在函数中,切片参数使用append,凭拼接的数据对原数据不会有影响,下面会有提到。

// 切片、map作为参数传参时,在被传参的函数中修改值,会影响原函数中数据、map的值

// 以map举例

func main() {
	m := map[int]string{1: "鱼儿", 2: "虾米"}
	fmt.Println("传参前:", m)
	update(m)
	fmt.Println("传参后:", m)
}

func update(m map[int]string) {
	m[1] = "鱼儿不存在"
}



**深度分析切片传参原值会被影响的原因**
/*
因为slice本质就是结构体,结构体里面有一个元素array 值指针类型(保存array的空间地址),作为参数传值时,其实就是传指针。如上函数举例:update方法实际就是获取array指针(array实际空间地址)进行操作,所以main函数打印时,发现原数据已经被修改。
*/
type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

 

12.指针*,与中括号[]的优先级

中括号[] 优先级高于 指针符号*

13.数组指针有P[0]的简写方式,切片指针没有p[0]的写法(区别)

func main() {
	s := []int{1, 2, 3, 54}
	var p *[]int
	p = &s
	fmt.Println(p)
	fmt.Println(*p)
	fmt.Println((*p)[0])
	fmt.Println(p[0]) // 此处报错!数组指针有P[0]的简写方式,切片指针没有p[0]的写法
}

 

14.浅拷贝、深拷贝的概念

浅拷贝:仅仅考别的变量的值,没有对指向的空间进行任何的拷贝
深拷贝:将原有的变量的空间全部拷贝一份

 

15 .可以通过append方法对切片进行动态扩容,但是对原数据没有影响。但是通过不同的切片定义方式,使用append方法后,再修改原数据包含下标的数据,对原数据都是没有影响的。原因:当使用append()方法后,就会自动创建新的空间,所以对原数据没有影响

func main() {
	//a := []int{1, 2, 3, 4, 5} //无论哪种切片的定义方式、无论空余cap多大,一旦涉及append,就会重新生成一个新的空间进行拼接
	var a = make([]int, 2, 10) // 使用该方式定义切片,modify()修改的值会改变main()值;使用上面自动推导类型定义,modify()修改的值不会改变
	a = []int{8, 9}
	//fmt.Println("a2:", a2)
	fmt.Println("原函数1", a)
	modify(a)
	fmt.Println("原函数2", a)
}
func modify(a1 []int) {
	// 使用append进行动态扩容时,a的指向不再是主函数a的空间,而是指向新的空间
	a1 = append(a1, 21) //注释该行代码,即可修改主函数中的数据
	a1[0] = 111
	fmt.Println(a1)
}

16.switch  golang语法中的switch与java等其他语言的语法不太相同

    查看https://www.jianshu.com/p/bb3cf84721ab

 

17.调用结构体的3种方式

// 方法值与方法表达式
type People struct {
	id   int
	name string
}

func (p *People) PrintInfo() {
	fmt.Println(*p)
}

func main() {
	p := People{101, "小明"}
	// 方式一:直接调用方法
	p.PrintInfo()
	// 方式二:方法值
	f := p.PrintInfo //可以打印下f的类型
	fmt.Printf("f的类型:%T\n", f)
	f()
	// 方式三:方法表达式
	f_ := (*People).PrintInfo
	f_(&p)
}

结果:Go语言学习--避免入坑版_第1张图片

 

18.文件操作,写入数据(三种方式)

// 方式一:WriteString
n,err:=file.WriteString("Hello World")

// 方式二:Write
var str string="Hello World"
n,err:=file.Write([]byte(str))

// 方式三:WriteAt
n,err:=file.WriteAt([]byte(str),0)//第二个参数,off表示在指定的位置重置写入数据

// 获取文件的长度,通常与WriteAt的长度结合使用
file.Seek(offset,io.SeekEnd)//将光标定位到文件中原有内容的后面,返回文件中原有数据的长度。其中offset表示在yauncheng文件后面空出的长度

19.go也能开发桌面软件-go get github.com/lxn/walk

20.判断map中的key,value是否存在

/*
	   判断map中的key,value是否存在
	*/
	m11 := map[int]string{}
	m11[1] = "123"
	m11[2] = "223"
	m11[3] = "323"
	m11[100] = "423"
	m11[5] = "523"
	m11[6] = "623"
	/*
		   注意重点:
		   	以下方法可以判断该值是否存在,如果不存在,b为false,v为空
									        存在,b为true,v为值
	*/
	v, b := m11[1001]
	fmt.Printf("%s", v)
	fmt.Println(b)


//输出结果 :false

19.打印空字符串 %q

 

20.map 的delete ,如果该值不存在,不会报错。这是map的特性

 

21.结构体传参:

1.将结构体变量拷贝一份,传递。--几乎不用。内存消耗大,效率低
2.将结构体变量地址值,传递(传引用)。---使用频率非常高
3.unSafe.Sizeof(变量名)-->此种类型的变量所占用的内存空间大小
4.unSafe.Sizeof(指针):不管何总类型的指针,在64位操作系统下,大小一致。均为8字节!!!

22.结构体变量的比较:

  

1.比较:只能使用==和!=  不能> < >= <= ...
2.相同结构体类型(成员变量的类型、个数、顺序一致)变量之间可以直接赋值(注意:如果顺序不一致,就认为不是同一个结构体)

23.结构体指针做函数返回值:

   

1.不能返回局部变量的地址值---局部变量保存栈帧上,函数调用结束后,栈帧释放。
                           局部变量的地址,不再受系统保护,随时可能分配给其他程序。
2.可以返回局部变量的值。

 

你可能感兴趣的:(Go语言学习--避免入坑版)