Go语言基础知识点整理

这里主要记载Go语言对于Java的不同用法~

注释和转义字符

1.注释

注释快捷键:ctrl+/

2.转义字符

(1),go的字符串只能使用双引号,所以想在字符串中显示单引号,那么就得使用转义字符

fmt.Println("\"hello world\"")

(2),go支持反引号,反引号引起来的字符串不支持转义

fmt.Println(`"hello\n world"`)
//输出为:"hello\n world"

(3),单引号只能用来包裹一个字节的ASCII码字符

var a int = '中'

(4),其他转义字符

\"双引号
\\反斜线
\a报警声
\t制表符
\b退格
\f换页
\n
\v垂直制表符

3.格式化字符串

  • Print -->函数直接输出内容
  • Printf -->格式化输出字符串
  • Println -->会在输出内容的结尾添加一个换行符
  • %v -->按值的本来值输出
  • %+v -->在%v基础上,对结构体字段名和值进行展开%#v输出Go语言语法格式的值
  • %T -->输出Go语言语法格式的类型和值
  • %% -->输出%本体%b(oOdxX)整型的不同方式显示
  • %U -->Unicode字符
  • %s -->字符串
  • %d -->整数
  • %f -->浮点数
  • %p -->指针,十六进制方式显示

二,变量和常量:

1.变量

在go语言中变量的数据类型是要放在变量名后面的

(1)变量声明的格式:

①:var+变量名+数据类型+“=”+变量值(其中数据类型可以省略)
②:简写:变量名+“:=”+变量值
③:批量声明:
var(变量名1+数据类型+“=”+变量值
变量名2+数据类型+“=”+变量值
变量名3+数据类型+“=”+变量值

)

(2)特点

①Go语言会自动推断变量值类型,即在声明变量时可以将变量类型省略
②定义变量之后必须要使用,否则会报错。批量声明的变量可以不被使用

2.常量(Constant)

(1)常量的声明格式

①:const+常量名+数值类型+“=”+常量值
②:批量声明:
const(变量名1+数据类型+“=”+变量值
变量名2+数据类型+“=”+变量值
变量名3+数据类型+“=”+变量值

)
const a int=1

(2)特点

①常量在声明之后不可以被修改
②在声明时必须被赋值

(3)iota

批量声明时可以使用iota用来实现常量的计数功能,iota就是当前变量的层数(每一个括号里面会从0开始算)

3.全局变量

将变量声明在函数之外。全局变量在声明后可以不被使用

4.跨包变量

在当前项目中创建一个version目录,在version目录中创建一个.go文档
在主程序中就可以引入该包进行使用

package main
import (
    "fmt"
    "go_study/version"
)
func main(){
    fmt.Println(version.Version)
}

如果某变量需要跨包使用,则该变量首字母需要大写

三,基本数据类型

1.字符串

bute:uint8的别名
rune:uint32的别名
字符串型的变量值要使用’ ’

2.布尔型

bool–>true/false

3.字符型

len():输出字符串的字节长度

四,运算符

1.算数运算符

+,-,*,/,%
在go中没有前++,只有后++
没有次方,"^"表示异或

2.位运算符

&按位与 全1为1
| 按位或 有1为1
^按位异或 相同为0,不同为1
“>>”:往右移两位
“<<”:往左移两位

3.赋值运算符

+= -= *= /=

4.逻辑运算符

&& 与 || 或 !非
逻辑运算符只针对布尔类型的数据值或者表达式使用

五,判断语句

1.if else

①,条件不需要加括号,但是加了之后也不会报错
②,if后面的左大括号必须和if在同一行,否则编译不通过
③,if的简短语句
在进行判断之前,可以声明变量,用于接收函数返回值并判断

if i:=3;i>8{
    fmt.Println("大于0")
}

2.switch case

(1)用法:

在go中每个执行语句后面默认带有break语句,可以使用fallthrough来表示继续执行后面的代码

switch{
    case 条件语句1:
    执行语句1
    case 条件语句2:
    执行语句2
    ……
}

(2)与if else的区别:

if else是多个条件选一个,只要成立了一个,后面的就都不会去匹配了
switch的每一个case是从上到下去匹配,如果没有break,则每一个条件都会去匹配

六,循环语句

1.for循环

go里面没有while循环,只有for循环这一种
想要实现无限循环可以去掉for的循环条件
for语句后面的三个构成部分不能加括号,否则会报错

2.break与continue

break是结束循环(直接跳出了循环,跳出循环后不再执行循环语句),continue是跳出本次for循环,直接进行下一次的循环(结束本次循环后重新开启本次循环)。continue后面的代码就不会执行了

七,label标签与goto

Go语言支持label(标签)语法:分别是break label,goto label,continue label

1.break label:

跳出循环不再执行for循环里的代码,一般用于跳出多层循环
break label只能用于for循环,不能和switch一起使用,标签要放在break的前面
在for循环外层定义一个标签,例如:“target:”,可以直接跳出最外层的循环

start:
    for i := 0; i < 6; i++ {
       for j := 0; j < 8; j++ {
          fmt.Print("*")
          if i == 2 && j == 2 {
             break start
          }
       }
       fmt.Println()
    }
    输出:
    ********
    ********
    ***

2.continue label:

continue label和break label功能相似,区别在于breaklabel是强制终止,continue label是继续循环下一个迭代

start:
    for i := 0; i < 6; i++ {
       for j := 0; j < 8; j++ {
          fmt.Print("*")
          if i == 2 && j == 2 {
             continue start
          }
       }
       fmt.Println()
    }
    输出:
    ********
    ********
    ***********
    ********
    ********

由此可见,在三行三列这一行代码执行完毕之后,跳出循环,又来到第四行第一列的位置继续执行代码

3.goto label:

goto可以无条件的跳转执行的位置,但是不能跨函数,需要配合标签使用
goto的标签放在goto的上面和下面都可以
例:使用goto实现循环

var name string
start:
    fmt.Println("请输入用户名")
    fmt.Scanln(&name)

    if name != "1" {
       goto start
    }
    fmt.Println("登录成功")
}

八,指针

1.值传递和址传递:

①,值传递:例如在主函数定义一个变量name,在主函数外部定义一个setName的函数需要传递一个name参数,此时就会将传过去的name参数在内存中另外开辟一块空间进行拷贝,再将新地址中的数据传递给setName函数,此时在setName函数中修改name的值,主函数中name的值不会发生变化
②,址传递:在传参时直接将主函数中的name的地址值传给setName函数,此时setName函数和主函数中的name使用同一个地址,在setName函数中修改name的值,主函数中name的值也会发生变化
址传递的变量类型为:“*string”,如要修改name的值,应使用:name=" "
可以使用&来获取某个变量的内存地址,用
获取到内存地址所对应的值

九,defer

1.延迟执行的函数会被压入栈中,return后按照先进后出的顺序调用
2.延迟执行的函数其参数会立即求值
3.可用于函数的异常捕获

十,init函数

1.init函数可以在所有程序执行开始前被调用,并且每个包下可以有多个init函数
2.init函数先于main函数自动执行
3.每个包中可以有多个init函数,每个包中的源文件中也可以有多个init函数
4.init函数没有输入参数,返回值,也未声明,所以无法引用
5.不同包的init函数按照包导入的依赖关系决定执行顺序
6.无论包被导入多少次,init 函数只会被调用一次, 也就是只执行一次
7. init 函数在代码中不能被显示的调用,不能被引用(赋值给函数变量),否则会出现编泽错误
8. Go程序仅仅想要用一个package的init执行,我们可以这样使用: import_" test xxx",导入包的时候加上下划线就ok了
9. init 函数不应该依赖任何在main函数里创建的变量,因为init函数的执行是在main函数之前的
10.执行顺序:
被依赖的全局变量> >被依赖包的init函数> >… > > main包的全局变量> > main的init函数> > main函数

十一,包

1.包的导入:import “包名”
要使用其他包内的函数,直接将包导入之后就可以用"包名+.+函数名"即可调用函数,不需要加文件名
2.需要导入的包过多时,可以简写
import{
包名1
包名2
包名3
……
}
3.起别名
如果有两个一样的包,那么在导入的时候就可以起一个别名
import{
pkg1 “demo/pkg”
pkg2 “demo/pkg”
}
起一个别名后在使用包时直接使用包的别名,如果使用包的原来名称会报错
4.全部引入
在使用包中的函数,变量时。通常是包名点变量名,如果想直接使用变量名,那么需要将包中的内容全部导入

十二,数组

1.数组的定义

var arr ([3]int= [3] int {1,2,3}||arr :=[...]int{1,3,5,7}

简写:

var arr = [...] int {1,2,3}//(go语言可以自动推断数组长度)

十三,map

map是key-value的形式,其中key只能是基本数据类型

1,map的声明:定义并创建

func main() {
    var mapSlice = make([]map[string]string, 3)
    for index, value := range mapSlice {
       fmt.Printf("index:%d value:%v\n", index, value)
    }
    fmt.Println("初始化元素:")
    //对切片中的map元素进行初始化
    mapSlice[0] = make(map[string]string)
    mapSlice[0]["name"] = "小明"
    mapSlice[0]["gender"] = "男"
    mapSlice[0]["address"] = "中国"
    for index, value := range mapSlice {
       fmt.Printf("index:%d value:%v\n", index, value)
    }
}

简写:

m:= map[string]string{
    "name":"张三",func main() {
    m := make(map[string][]string)
    fmt.Println(m)
    val := []string{"北京", "上海"}
    m["中国"] = val
    fmt.Println(m)
    m["中国"] = append(m["中国"], "广州", "深圳")
    fmt.Println(m)
}
    "age":"12",
}

2.常用方法

(1)查找

通过双赋值检测某个key是否存在

v,ok:= m2["name"]
if ok{
    //如果存在ok就为true
    fmt.Printf("v= %v",v)
}else{
    fmt.Pringf("v不存在")
}

(2)删除

delete(map,key)//删除单个元素

要删除所有key-value,可以重新make

(3)遍历

map只有len,没有cap
len一个map,得到的就是key的个数
只有for range一种遍历方式
for key,value :=range n{
    fmt.Printf("key=%v,value=%v\n",key,value)
}

3.map扩展

(1)切片中的元素为map类型

var mapSlice = make([]map[string]string, 3)
for index, value := range mapSlice {
    fmt.Printf("index:%d value:%v\n", index, value)
    //对切片中的map元素进行初始化
    mapSlice[0] = make(map[string]string)
    mapSlice[0]["name"] = "小明"
    mapSlice[0]["gender"] = "男"
    mapSlice[0]["address"] = "中国"
    for index, value := range mapSlice {
       fmt.Printf("index:%d value:%v\n", index, value)
    }
}

(2)map中的值为切片类型

func main() {
    m := make(map[string][]string)
    fmt.Println(m)
    val := []string{"北京", "上海"}
    m["中国"] = val
    fmt.Println(m)
    m["中国"] = append(m["中国"], "广州", "深圳")
    fmt.Println(m)
}

十四,自定义数据类型和类型别名

1.自定义数据类型

type msgType uint16//–>自定义一个数据类型为uint16的新的数据类型msgType
此时msgType与uint16是属于不同的数据类型,如果要将uint16的变量赋值给msgType的变量,则需要进行类型转换

2.类型别名

byte是uint8的别名
rune是int32的别名
type msgType = uint16
类型别名就相当于是将uint16起了一个别的名字
赋值的时候也不用类型转换

十五,结构体

由一组字段构成的一种自定义数据类型

1.实例化结构体对象的方法

//创建一个结构体
type User struct {
    Name string
    Age int
    password string
}

(1)

var u1 User = User{"张三", 22, "#256as"}
fmt.Printf("u1:%v u1的类型为:%T", u1, u1)

以这种方式进行实例化时,括号内的参数顺要和创建结构体时参数的顺序相同

(2)以传参的方式进行实例化

var u2 User = User{
    Name:"李四",
    password: "$11902dd",
    Age: 18,
}
fmt.Printf("u2:%v u2的类型为:%T", u2, u2)

(3)声明一个结构体对象,以赋值的方式进行实例化

var u3 User
u3.Name = "王五"
u3.Age = 25
u3.password = "*22998aas"
fmt.Printf("u3:%v u2的类型为:%T", u3, u3)

2.结构体继承

type User struct {
    Name     string
    Age      int
    password string
}

type Account struct {
    money float32
    User
}

func main() {
    var ac Account = Account{
       money: 21.5,
       User: User{
          Name:     "张三",
          Age:      21,
          password: "*129987hhc",
       },
    }
    fmt.Printf("ac %#v,%T\n", ac, ac)
}
type User struct {
    Name     string
    Age      int
    password string
}

type Account struct {
    money float32
    User
}

func main() {
    var u1 User = User{
       Name:     "张三",
       Age:      21,
       password: "*129987hhc",
    }
    var ac Account = Account{
       money: 21.5,
       User:  u1,
    }
    fmt.Printf("ac %#v,%T\n", ac, ac)
}

3.结构体方法

在继承结构体时,该结构体的方法也被继承

type User struct {
    Name     string
    Age      int
    password string
}

type Account struct {
    money float32
    User
}

func (u User) PrintName() string {
    fmt.Println("printName方法:", u)
    fmt.Printf("printName方法内部: %p\n", &u)
    return u.Name
}

func main() {
    user := User{"李四", 23, "03396aac"}
    fmt.Printf("main:%p\n", &user)
    name := user.PrintName() //是值传递
    fmt.Println(name, user)

    account := Account{
       money: 234,
       User:  user,
    }
    name = account.PrintName()
    fmt.Println(name)
}

4.结构体指针

如果想要修改结构体里面的值,需要使用指针

type Accounts struct {
    Name string
    Age  int
}

// ac是拷贝的,修改无效
func (ac Accounts) setAge(age int) {
    ac.Age = age
}

// ac是执行原结构体User的
func (ac *Accounts) setName(name string) {
    (*ac).Name = name
}

func main() {
    accounts := &Accounts{"张三", 23}
    accounts.setName("李四")
    accounts.setAge(12)
    fmt.Println(accounts)
}
输出结果:
&{李四 23}

5.结构体标签

import (
    "encoding/json"
    "fmt"
)

type Article struct {
    Title     string `json:"title"`
    UserName  string `json:"-"` //-也不参与序列化
    LookCount int    `json:"lookCount"`
    Free      bool   `json:"free"`
    password  string `json:"password"` //小写字母开头的不会参与序列化
}

func main() {
    article := Article{
       Title:     "golang文档",
       UserName:  "张三",
       LookCount: 1024,
       Free:      true,
       password:  "12334¥ssa",
    }

    //结构体转json
    jsonData, err := json.Marshal(article)
    if err != nil {
       fmt.Println(err)
       return
    }
    jsonStr := string(jsonData)
    fmt.Println(jsonStr)
}

输出结果:
{"title":"golang文档","lookCount":1024,"free":true}

十六,接口

type Animal interface {
    Sing()
    Dump(time string)
    Rap() string
}

type Chicken struct {
    Name string
}

func (c Chicken) Sing() {
    fmt.Println("调用了Sing方法")
}

func (c Chicken) Dump(time string) {
    fmt.Println("调用了Dump方法")
}

func (c Chicken) Rap() string {
    fmt.Println("调用了Rap方法")
    return "rap"
}

func main() {
    var animal Animal
    animal = Chicken{"33"}
    animal.Sing()
    animal.Dump("2")
    animal.Rap()
}

type Animal interface {
    Sing()
}

type Chicken struct {
    Name string
}

func (c Chicken) Sing() {
    fmt.Println("chicken调用了Sing方法")
}

type Cat struct {
    Name string
}

func (cat Cat) Sing() {
    fmt.Println("cat调用了Sing方法")
}

func Sing(animal Animal) {
    animal.Sing()
}

func main() {
    chicken := Chicken{"33"}
    cat := Cat{"44"}
    Sing(chicken)
    Sing(cat)
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值