Go:Golang Tip
目录:
iota的使用
- iota在const关键字出现时将被重置为0
- const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
- 使用iota能简化定义,在定义枚举时很有用。
const (
_ = iota
KB = 1 << (10 * iota)
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)
默认小数为float64
package main
import "fmt"
func main() {
f1 := 1.2345
fmt.Printf("%T", f1)
}
打印结果为float64
字符串相关
字符串转义
package main
import "fmt"
func main() {
f1 := "\"\\\""
fmt.Printf(f1)
f2 := `"\"`
fmt.Printf(f2)
}
第一种是通过\
进行转义,第二种是直接使用飘号
字符串拼接
package main
import "fmt"
var f1 = "why"
var f2 = "wanghongyu"
func main() {
f1 := "why2"
f2 := "wanghongyu2"
s := fmt.Sprintf("%s%s",f1, f2)
fmt.Printf(s)
}
打印结果为why2wanghongyu2
,这里注意
字符串分割
package main
import "strings"
import "fmt"
func main() {
f1 := "w-h-y"
s := strings.Split(f1, "-")
fmt.Println(s)
fmt.Printf("%T", s)
}
打印结果
[w h y]
[]string
字符串包含
package main
import "strings"
import "fmt"
func main() {
f1 := "wanghongyu"
// 包含
s1 := strings.Contains(f1, "hong")
// 前缀
s2 := strings.HasPrefix(f1, "wang")
// 后缀
s3 := strings.HasSuffix(f1, "yu")
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
}
打印结果
true
true
true
字符串拼接
package main
import "strings"
import "fmt"
func main() {
var s1 []string
s1 = []string{"wang","hong","yu"}
fmt.Println(strings.Join(s1, "+"))
}
打印结果
wang+hong+yu
字符串循环
package main
import "fmt"
func main() {
f := "wanghongyu"
for k, v := range f {
fmt.Printf("%v %c\n", k, v)
}
}
打印结果
0 w
1 a
2 n
3 g
4 h
5 o
6 n
7 g
8 y
9 u
字符串修改
package main
import "fmt"
func main() {
f1 := "白萝卜"
f2 := []rune(f1)
f2[0] = '红'
fmt.Println(string(f2))
}
slice相关
slice定义
package main
import "fmt"
func main() {
s1 := [3]bool{true, true, true}
s2 := [...]int{1, 2, 4, 8, 16}
s3 := [5]int{0: 1, 3: 2}
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
}
slice遍历
package main
import "fmt"
func main() {
s1 := [...]int{1, 2, 4, 8, 16}
for i := 0; i < len(s1); i++{
fmt.Println(i, s1[i])
}
for k, v := range s1{
fmt.Println(k, v)
}
}
slice没有开辟内存空间为nil
cat fudianshu.go
package main
// import "strings"
import "fmt"
func main() {
var s1 []int
fmt.Println(s1 == nil)
s1 = []int{1, 2, 3}
fmt.Println(s1 == nil)
}
打印结果
true
false
slice为连续内存
go的list是一块连续的内存,其他语言是将各种内存地址放到一个框
slice复制
package main
import "fmt"
func main() {
s1 := []int{1, 3, 5}
s2 := s1
var s3 make([]int, 3, 3)
copy(s3, s1)
fmt.Println(s1, s2, s3)
s1[0] = 100
fmt.Println(s1, s2, s3)
}
slice添加元素
package main
import "fmt"
func main() {
s1 := []int{1, 3, 5}
fmt.Printf("len(s1): %d, cap(s1): %d\n", len(s1), cap(s1))
s1 = append(s1, 7)
fmt.Printf("len(s1): %d, cap(s1): %d\n", len(s1), cap(s1))
}
打印结果
len(s1): 3, cap(s1): 3
len(s1): 4, cap(s1): 6
slice删除元素
go语言中没有提供删除元素,需要用slice本身的特性来删除元素
示例删除第三个元素
package main
import "fmt"
func main() {
s1 := []int{1, 3, 5, 7, 9}
s1 = append(s1[:2], s1[3:]...)
fmt.Println(s1)
fmt.Println(cap(s1))
}
打印结果
[1 3 7 9]
5
slice排序
package main
import "fmt"
import "sort"
func main() {
s1 := []int{3, 5, 7, 9, 1}
sort.Ints(s1)
fmt.Println(s1)
}
指针
package main
import "fmt"
func main() {
n := 18
// 取地址
p := &n
fmt.Println(p)
fmt.Printf("%T\n", p)
// 根据地址取值
m := *p
fmt.Println(m)
fmt.Printf("%T\n", m)
}
打印结果
0xc420014088
*int
18
int
map
map需要make从初始化
package main
import "fmt"
func main() {
m1 := make(map[string]int, 10)
m1["why"] = 26
m1["pqt"] = 25
fmt.Println(m1)
fmt.Println(m1["why"])
value, ok := m1["mb"]
if !ok {
fmt.Println("没有key")
}else{
fmt.Println(value)
}
}
打印结果
map[why:26 pqt:25]
26
没有key
map遍历
package main
import "fmt"
func main() {
m1 := make(map[string]int, 10)
m1["why"] = 26
m1["pqt"] = 25
for k, v := range m1{
fmt.Println(k, v)
}
}
打印结果
pqt 25
why 26
map删除元素
package main
import "fmt"
func main() {
m1 := make(map[string]int, 10)
m1["why"] = 26
m1["pqt"] = 25
for k, v := range m1{
fmt.Println(k, v)
}
}
打印结果
map[why:26 pqt:25]
map[why:26]
方法
创建方法
package main
import "fmt"
func f1(x int, y int) {
fmt.Println(x + y)
}
func f2() {
fmt.Println("f2")
}
func f3() int {
return 3
}
func f4(x, y int) (ret int) {
ret = x + y
return
}
func f5(x string, y ...int) int {
fmt.Println(x)
fmt.Println(y) // []int
return 1
}
func main() {
f1(1, 2)
f2()
fmt.Println(f3())
fmt.Println(f4(3, 4))
f5("why", 2, 3, 4)
}
打印结果
3
f2
3
7
why
[2 3 4]
defer
defer到函数执行完成后执行
package main
import "fmt"
func f(){
fmt.Println("before")
defer fmt.Println("111")
defer fmt.Println("222")
defer fmt.Println("333")
fmt.Println("after")
}
func main() {return
f()
}
打印结果
before
after
333
222
111
go在底层执行函数的return语句并非一个原子操作,而是分两步,返回值赋值->return,在加上defer就变为了返回值赋值->defer->return
匿名函数
其实我想不明白既然只用一次为啥要弄个函数
panic和recover
recover只能用在defer中才能生效
package main
import "fmt"
func f1() {
fmt.Println("f1")
defer func() {
err := recover()
if err != nil {
fmt.Println(err)
fmt.Println("recover")
}
}()
panic("panic")
}
func f2(){
fmt.Println("f2")
}
func main(){
f1()
f2()
}
打印结果
f1
panic
recover
f2
递归
示例是一个阶乘的例子
func f(n uint64) uint64 {
if n <= 1 {
return 1
}
return n * f(n - 1)
}
func main() {
ret := f(7)
fmt.Println(ret)
}
打印结果
5040
struct
struct使用的连续内存
package main
import "fmt"
type x struct {
a int
b int
c int
}
func main() {
m := x{
a: 10,
b: 20,
c: 30,
}
fmt.Printf("%p\n", &(m.a))
fmt.Printf("%p\n", &(m.b))
fmt.Printf("%p\n", &(m.c))
}
打印结果
0xc4200120e0
0xc4200120e8
0xc4200120f0
struct实现其他语言的构造方法
package main
import "fmt"
type persion struct {
name string
age int
}
func newPersion(name string, age int) *persion {
return &persion {
name: name,
age: age,
}
}
func main() {
p1 := newPersion("why", 26)
p2 := newPersion("pqt", 25)
fmt.Println(p1)
fmt.Println(p2)
打印结果
&{why 26}
&{pqt 25}
方法指定接收者
package main
import "fmt"
type persion struct {
name string
age int
}
func newPersion(name string, age int) *persion {
return &persion {
name: name,
age: age,
}
}
func (p *persion) newyear() {
p.age++
}
func main() {
p1 := newPersion("why", 26)
fmt.Println(p1)
p1.newyear()
fmt.Println(p1)
}
打印结果
&{why 26}
&{why 27}
就是其他语言的类方法了,这里的p在python里就是self,在js里就是this
结构体嵌套
结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)
package main
import "fmt"
type Persion struct {
Name string
Age int
Address // 匿名嵌套结构体
}
type Address struct {
Province string
City string
}
func newPersion(name string, age int, province string, city string) *Persion {
return &Persion {
Name: name,
Age: age,
Address: Address{
Province: province,
City: city,
},
}
}
func main() {
p1 := newPersion(
"why",
26,
"hebei",
"chengde",
)
fmt.Println(p1.Address.Province)
fmt.Println(p1.City)
}
可以使用p1.Address.Province
和p1.Province
两种方式,前提是大的结构体内只有一个此名字段
struct实现继承
package main
import "fmt"
type Persion struct {
Name string
Age int
}
type Man struct {
Persion
Height int
}
func (p *Persion) newyear() {
p.Age++
}
func main() {
p1 := Man{}
p1.Age = 26
fmt.Println(p1.Age)
p1.newyear()
fmt.Println(p1.Age)
}
json序列化与反序列化
package main
import "fmt"
import "encoding/json"
type persion struct {
name string
age int
}
func main() {
p1 := persion{
name: "why",
age: 26,
}
// 序列化
b, err := json.Marshal(p1)
if err != nil {
fmt.Printf("marshal failed, err: %v", err)
return
}
fmt.Printf("%v", p1)
fmt.Printf("%v", string(b))
str := `{"name": "qpt", "age": 25}`
var p2 persion
// 反序列化
json.Unmarshal([]byte(str), &p2)
fmt.Printf("%v", p2)
}
接口
接口定义
package main
import "fmt"
type speaker interface{
speak()
}
type cat struct{}
type dog struct{}
func (c cat) speak() {
fmt.Println("miao~")
}
func (d dog) speak() {
fmt.Println("wang~")
}
func da(x speaker) {
x.speak()
}
func main() {
var c cat
var d dog
da(c)
da(d)
}
打印结果
miao~
wang~
使用变量也和以前一样
package main
import "fmt"
type speaker interface{
speak()
}
type cat struct{
aaa string
}
type dog struct{
aaa string
}
func (c cat) speak() {
fmt.Printf("%v~\n", c.aaa)
}
func (d dog) speak() {
fmt.Printf("%v~\n", d.aaa)
}
func da(x speaker) {
x.speak()
}
func main() {
c := cat{aaa: "miao",}
d := dog{aaa: "wang",}
da(c)
da(d)
}
接口也是一个类型,分两个部分,一部分存类型,另一部分存类型的值
接口嵌套
// Sayer 接口
type Sayer interface {
say()
}
// Mover 接口
type Mover interface {
move()
}
// 接口嵌套
type animal interface {
Sayer
Mover
空接口
package main
import "fmt"
func main() {
m1 := make(map[string]interface{}, 16)
m1["name"] = "why"
m1["age"] = 26
m1["hobby"] = [...]string{"唱", "跳", "rap", "篮球"}
fmt.Println(m1)
}
打印结果
map[age:26 name:why hobby:[唱 跳 rap 篮球]]
可以用于方法的传参数
包
导入包
包的路径是以src为根目录
.
├── demo
│ └── main.go
└─── demopackage
└── calc.go
calc.go
package calc
func Add(x, y int) int {
return x + y
}
首字符大写包外可见
main.go
package main
import "fmt"
import calc "demopackage"
func main() {
a := calc.Add(3, 7)
fmt.Println(a)
}
匿名导入
import _ "包的路径"
匿名导入只会执行包的init方法,init方法没有参数也没有返回值
匿名导入多个包的执行顺序
交集,差集和并集
func union(slice1, slice2 []string) []string {
m := make(map[string]int)
for _, v := range slice1 {
m[v]++
}
for _, v := range slice2 {
times, _ := m[v]
if times == 0 {
slice1 = append(slice1, v)
}
}
return slice1
}
//求交集
func intersect(slice1, slice2 []string) []string {
m := make(map[string]int)
nn := make([]string, 0)
for _, v := range slice1 {
m[v]++
}
for _, v := range slice2 {
times, _ := m[v]
if times == 1 {
nn = append(nn, v)
}
}
return nn
}
//求差集 slice1-并集
func difference(slice1, slice2 []string) []string {
m := make(map[string]int)
nn := make([]string, 0)
inter := intersect(slice1, slice2)
for _, v := range inter {
m[v]++
}
for _, value := range slice1 {
times, _ := m[value]
if times == 0 {
nn = append(nn, value)
}
}
return nn
}