go语言基础知识

255 阅读15分钟

go中包到定义

package,是多个go源码的集合。
是一种高级的·代码复用·的方案。
go语言为我们提供了很多的内置包,比如fmt,strconv,strings,sort,errors, time,
encoding/json os io等内置包,
strconv:
     包strconv主要实现对字符串和其他基本数据类型之间的转换。基本数据类型包括:布尔、整型(包括有/无符号、二进制、八进制、十进制和十六进制)和浮点型等。
strings包主要是处理字符串的。
sort是排序包
errors是错误处理包
time是时间包

所谓的内置包,就是我们在进行代码开发的时候,可以直接使用,而不需要下载。

go中的包分为3大类,内置的包,自定义的包,第三方包(别人写的 git上开源的包)
自定义包,就是自己写的一个目录,目录中可以有很多的.go文件,文件中我们可以定义一些变量,函数,或者结构体,这样我们就可以使用了。

一个go项目中,最多只能有一个main包和main方法。
一个包中的.go文件的package 后面的包名,可以和所在的目录名相同,当然也可以不相同,但是一般来说,我们建议是写成一样的。

首字母大写,代表是公有
首字母小写,代表是私有
.go文件中的变量和函数,如果首字母是大写的,说明这个变量或函数是公有的,也就是说,可以被别包中的.go文件使用,如果是小写的,则代表是私有的,则只能在自己的包中使用,不能被被的包调用。

在.go文件中,我们可以定义变量,可以定义函数,也可以定义结构体。


包名是main的包是整个项目的入口包,这种包在编译之后会得到一个可执行的文件,
而编译没有包含的源代码则不会得到可执行文件。
一个项目中,只能有一个main方法和一个main包

不同的包中的.go文件是可以同名字的。
比如有一个calc的目录,其中有一个aaa.go文件
另外还有一个tools的目录,其中也有一个aaa.go文件,这是可以的。

一个包中(目录中),可以写多个.go文件,但是不同.go中的函数名称不能重复。
一个包中的多个.go文件中的方法名不能重复。

当我们import一个包的时候,可以给起一个别名,这种做法主要是为了针对包名特别长的情况。

当我们import一个包,但是在下面的代码中没有使用,可以在包名前加一个_ 


第三方包: 都放在了 https://pkg.go.dev整个网站中,我们在使用的时候,可以直接去查找。

go.sum文件是自己生成的,我们不用管它。
当我们在.go文件中import某个我们依赖的包,并且通过go mod download 或 go get xxx
或者 go mod vnedor命令来下载依赖的包的时候,如果下载成功,则会自动的在go.mod文件中自动的require 添加上。


在go中,你可以理解为是以包为单位的(及以package为单位).
在同一个目录下,所有文件的package都必须是相同的。虽然package的名字不一定是所在目录的名字,
但是一定得相同。
全局变量的使用范围是同一个包内,局部变量的使用范围是同一个{}内。
在同一个目录下,所有文件的package都是一样的,那么a.go文件中就可以去调用b.go文件中的变量,
c.go文件也可以去调用d.go文件中的变量。

注意:
 - 同一个包中调用函数,函数名定义没有特定要求。
 - 不同包调用函数或者变量时,函数名定义必须以大写字典开头,例如:`func Add() {}`,表示当前函数或变量是可公开调用的
 

图片.png

go mod

在命令行中,执行 go mod命令,我们可以看到有以下一些功能可以使用:

图片.png

 也就是说,go mod是一个大的方面的东西,其中有很多具体的功能可以使用。
 比如 go mod init 项目名
      go mod  tidy : 增加丢失的module ,去掉未用的module 
      go mod download :下载依赖的module到本地,,
                       放在gopath/pkg/mod/github.com中了,
                       这里统一存放所有下载的github中的包。
                       每个包都是一个文件夹。
      go mod vendor :把依赖复制到vendor目录下,及会在项目下创建一个vendor目录
      go mod edit : 编辑go.mod文件。
      
      

go env

图片.png

自动下载
go env -w GO111MODULE=on

设置环境为国内代理

go env -w GOPROXY=https://goproxy.cn,direct

go env -w GOSUMDB=off

下载第三方包的几种方法

<1>go get (一般不用该方法)

该命令也是可以下载我们依赖的第三方包的,
这个方法会把依赖的第三方包下载到本地。
比如 go get github.com/shopspring/decimal
但是这个方法可能会遇到网络的问题,在国内成功的概率不是很大。

<2>go mod download

  通过这种方法,依赖包会自动下载到$gopath/pkg/mod/cache/download目录中。多个项目可以共享。
  注意:
      使用go mod download下载第三方包的时候,首先你需要在你的项目中引入第三方包

<3>go mod vendor

  该方法会把依赖的包,下载复制到当前项目的vendor目录中

<4>go mod tidy

  一次性下载所有依赖的第三方包

go.mod文件

使用go mod这个依赖包管理工具,就不需要非得把项目放在gopath指定目录下,
你可以在你磁盘(电脑)的任何位置创建一个go项目,包含go.mod文件的目录也称为模块根,
也就是说,go.mod文件的出现定义了它所在的目录为一个模块。

go开发语言和编辑器(IDE)

go开发包(类似于python解释器)+ ide(golang,vscode,sublime text。。。。)
go开发包,和anaconada3,anaconda2这些差不多,都是一个开发包,有anaconda3/bin/python   go/bin/go 这就是sdk

golang:跟pycharm 90%相似,jetbrains公司,idea,用来开发java的,phpstorm,pycharm,goland

1 下载go开发包(这个建议就安装在c盘)
https://golang.google.cn/dl/   然后选择你自己对应的电脑版本,之后安装

2 go的解析器下载
直接百度搜索Goland然后选择官网去下载

3 下载好了之后我们就可以在cmd中查看自己的版本
go version 查看go的版本

go env    查看go的环境变量
GO111MODULE= # 没有值或者off,表示没有开启go mode模式,用的就是gopath模式
GOROOT=c:\go  # go开发包的安装路径,确认好是否对
GOPATH=C:\Users\Administrator\go # 代码存放路径,确认好是否对,以后你的go代码都放在这个文件夹下

在任意位置敲go,都有这个命令,需要把 c:\go\bin加入环境变量

go mode模式:代码可以放在任意路径

如何导入包import

在写Go代码的时候经常用到import这个命令用来导入包文件,看到的方式参考如下:
 import(
     "fmt"
 )

然后在代码里面可以通过如下的方式调用
  fmt.Println("hello world")

上面这个fmt是Go语言的标准库,他其实是去GOROOT下面加载该模块,当然Go的import还支持如下两种方式来加载自己写的模块:
  相对路径:import   "./model"  //当前文件同一目录的model目录,但是不建议这种方式import

  绝对路径:import   "shorturl/model"  //加载GOPATH/src/shorturl/model模块

 上面展示了一些import常用的几种方式,但是还有一些特殊的import,让很多新手很费解,下面是三种导入包的使用方法。

  (1)点操作   
      有时候会看到如下的方式导入包     import( . "fmt" ) 
      这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名.
      也就是前面你调用的fmt.Println(“hello world”)  可以省略的写成Println(“hello world”)

  (2)别名操作   
      别名操作顾名思义可以把包命名成另一个用起来`容易记忆`的名字
      import( f "fmt" )  
      别名操作调用包函数时前缀变成了重命名的前缀,即f.Println(“hello world”)

   (3)_操作   
      这个操作经常是让很多人费解的一个操作符,请看下面这个import

      import ( “database/sql” _ “github.com/ziutek/mymysql/godrv” ) 

    _操作其实只是引入该包。当导入一个包时,它所有的init()函数就会被执行,但有些时候并非真的需要使用这些包,仅仅是希望它的init()函数被执 行而已。
    这个时候就可以使用_操作引用该包了。
    即使用_操作引用包是无法通过包名来调用包中的导出函数,而是只是为了简单的调用其init函数()。

注释

//   在go语言中表示   单行注释使用

/*

。。。。。

。。。。。

*/  在go语言中表示   多行注释使用

函数的定义和调用

函数是基本的代码块,用于执行一个任务。

Go 语言最少有个 main() 函数。

你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。

函数声明告诉了编译器函数的名称,传入的参数,返回结果的类型。

Go 语言标准库提供了多种可动用的内置的函数。
例如,len() 函数可以接受不同类型参数并返回该类型的长度。
如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

go语言函数的一般定义格式如下:

func function_name( [parameter list] ) [return_types] {
函数体
}

函数定义解析:
    - func:函数由 func 开始声明,是定义函数时候的关键字,类似于python中的def关键字
    - function_name:函数名称,参数列表和返回值类型构成了函数签名。
    - parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
    - return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。
                   有些功能不需要返回值,这种情况下 return_types 不是必须的。
    - 函数体:函数定义的代码集合,具体的函数逻辑

<1>函数的定义

//以下实例为max()函数的代码,该函数传入两个整型参数 num1 和 num2,并返回这两个参数中的最大值:

//函数返回两个数的最大值 
func get_max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   
   return result
}

<2>函数的调用

当创建函数时,你定义了函数需要做什么,通过调用该函数来执行指定任务。
调用函数,向函数传递参数,并返回值,例如:
// 以下实例在 main() 函数中调用 max()函数,执行结果为:
package main

import "fmt"

func main() {
   // 定义局部变量 
   var a int = 100
   var b int = 200
   var ret int

   // 调用函数并返回最大值
   ret = get_max_value(a, b)

   fmt.Printf( "最大值是 : %d\n", ret )
}

// 函数返回两个数的最大值
func get_max_value(num1, num2 int) int {
   // 定义局部变量 
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result
}

在命令行运行go代码文件

go run xxxx.go
就像是python xxx.py文件

fmt包中的Println()和Printf()这2个函数的区别

总结:Println()可以打印所有类型的变量,并且是自动换行
     Printf():f是format()的意思,及只能打印格式化的字符串
package main

import "fmt"

func main() {

   num := "hello word!"  //这里声明了一个变量,赋值给num
   
   //Println()和Printf()的区别

   //相同点:
   //Println 与Printf 都是fmt 包中的公共方法,在需要打印信息时需要用到这两个函数

   // 不同点:
   //Println()打印的每一项之间都会有空行
   //可以打印出字符串和变量
   fmt.Println(num)

   //Printf()格式化输出
   //Printf()需要手动换行
   //Printf():只可以打印出格式化的字符串,可以输出字符串类型的变量,不可以输出整型变量和整型
   fmt.Printf("我要写的内容是:%s\n", num)
   fmt.Printf("我要写的内容是:%s", num)

}

时间time

参考网址:http://c.biancheng.net/view/5392.html
package main

import (
   "fmt"
   "time"
)

func main() {
   now := time.Now() //获取当前时间
   fmt.Printf("current time:%v\n", now)

   year := now.Year()     //年
   month := now.Month()   //月
   day := now.Day()       //日
   hour := now.Hour()     //小时
## minute := now.Minute() //分钟
   second := now.Second() //秒

   fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}

什么是go语言中的包package

包(package)是多个go源码的集合,是一种高级的代码复用方案。
go语言给我们提供了很多`内置`的包,如fmt,os,io等(类似于python中的内置的包或者函数,不需要我们再额外的安装install和导入import)。
当然仅仅使用内置的包,是不能满足我们的要求的。我们可以根据自己的需要创建自己的包。
一个包可以简单理解为是一个存放.go文件的文件夹。
该文件夹下的所有.go文件都要在代码的第一行声明该文件所属的包package
package 包名


注意事项:
一个文件夹下直接包含的文件只能属于一个包package,同样的,一个包package的文件不能在多个文件夹下。
包名可以不和文件夹的名字一样,包名不能包含-符号。

包名是main的包是应用程序的入口包,这是一个特殊的包。
这种包在编译之后会生成一个可执行文件,而其他的包在编译之后不会生成可执行文件。
如果想在一个包中引用另外一个包中的标识符(比如变量,常量,类型,函数)时,则该标识符必须是对外可见的。在go语言中,只需要把标识符(比如变量,常量,类型,函数)的首字母大写就可以了,这样就是对外可见的了。

结构体中的字段名和接口中的方法名,如果首字母是大写,外部包也是可以访问这些字段和方法的。例如:
type Student struct {
Name  string //可在包外访问的方法
class string //仅限包内访问的字段
}

type Payer interface {
        init() //仅限包内访问的方法
        Pay()  //可在包外访问的方法
}


要在代码中引用其他包的内容,需要使用import关键字导入使用的包。具体语法如下:
import '包的路径'

import导入语句通常放在文件开头包声明语句的下面。
导入的包名需要使用双引号包裹起来。
包名是从$GOPATH/[src](https://so.csdn.net/so/search?q=src&spm=1001.2101.3001.7020)/后开始计算的,使用/进行路径分隔。
Go语言中禁止循环导入包。


如果只希望导入包,而不使用包内部的数据时,可以使用匿名导入包。具体的格式如下:
import _ "包的路径"

图片.png

首字母大小写

golang中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称。
如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用。
可以简单的理解成,首字母大写是公有的,首字母小写是私有的

goroot和gopath的关系和区别

<1>goroot

 goroot其实就是golang语言的安装路径。
 当你安装完golang之后,这个其实就已经有了

<2>gopath

 作用:
    (1)存放sdk之外的第三方类库
    (2)自己收藏的可以复用的代码
  
 目录结构:
   gopath目录约定有3个子目录:src目录,pkg目录,bin目录。
   src目录存放源代码(比如:.go .c .h .s等) 按照golang默认约定,go run,go install等命令的当前工作路径(即在此路径下执行上述命令)。
   pkgn目录存放编译时生成的中间文件(比如:.a)  golang编译包时
   bin目录存放编译后生成的可执行文件
      为了方便,可以把此目录加入到PATH变量中 , 
      如果有多个gopath ,那么使用PATH变量中,如果有多个gopath,那么使用 PATH变量中,如果有多个gopath,那么使用{GOPATH/bin:}/bin添加所有的bin目录)

goland中的global gopath和project gopath

图片.png

这里有俩个一个是Global GOPATH 一个是Project GOPATH

Global GOPATH是所有项目都可以使用的

Project GOPATH是只有这个一个项目可以使用的

go安装第三方库/包

参考网址:https://www.jianshu.com/p/97738b026521

<1>前提

go安装第三方库/包的前提是:必须设置gopath
linux环境:
    ```
    vim /etc/profile
    export GOROOT=/usr/local/go  // 设置为你自己的go安装目录
    export GOPATH=$HOME/gocode   // 设置为自己的go项目的工作区间
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin  // 原路径后用冒号连接新路径

    source /etc/profile  // 使文件立刻生效
    ```

mac环境:
    ```
    cd ~
    vim .bash_profile
    export GOROOT=/usr/local/opt/go@1.9/libexec  //golang安装路径
    export GOPATH=/usr/local/Cellar/go/1.7.6   // 工作路径
    export GOBIN=$GOPATH/bin  // 可执行文件
    export PATH=$PATH:$GOROOT/bin:$GOBIN  // path导入路径

    source ~/.bash_profile  // 使文件立刻生效
    ```

win环境:
window : GOPATH,额外 安装git

    其实linux和mac系统也需要git,不过这两者都默认拥有git。而windows是需要自主安装的

    1.  去git官网下载git并安装

    1.  再设置GOPATH:

        右键我的电脑——高级系统设置——环境变量,系统变量下 点击【新建】
        输入: 第1行:GOPATH 第2行:你指定路径,例如: D:\go\gopath (注意去掉末尾的分号)

 

<2>golang安装第三包的方式

(1)自动安装:通过`go get xxx`命令来安装
    这条命令会把远端的第三方包下载并解压到你的`GOPATH`路径下的`src文件夹`里面去,并执行`go install xxx`命令来安装该包,结果是在`GOPATH`路径的`pkg文件夹`生成`xxx.a`文件

    实际上`go get`就是`git clone` + `go install`的组合
    由上面可知, windows在调用`go get`之时使用到了`git`,所以必须先安装安装`git`

(2)手动安装:

    先下载该包,并按照该包官方的下载路径 为该包创建对应的`gopath/src`下里面的路径,

    注意这一步很关键!第三包在src里的路径不能随意放在一个文件夹中,因为第三方包内部的文件里还有对其它包的引用,如果随意放置会导致导入路径失效。

    将包移入到该路径,执行`go install`命令安装这个文件

go.mod文件

图片.png

go环境的一些修改

自动下载

go env -w GO111MODULE=on

设置环境为国内代理

go env -w GOPROXY=https://goproxy.cn,direct

内置函数make

内置函数make,是用来为slice,map或者chan3种类型分配内存哈初始化一个对象的。
注意:make只能用在这3种类型上。
package main

// slice类型的对象
func main() {
   // 初始化一个有5个整型元素的列表
   // 规定了slice对象的容量是10,也就是说,我还可以往slice_1中添加5个元素
   var slice_1 []int = make([]int, 5, 10)
   fmt.Println(slice_1)
   
   // 初始化一个有5个整型元素的列表,这里没有规定该slice对象的容量
   var slice_2 []int = make([]int, 5)
   fmt.Println(slice_2)

}

// map类型的对象
func main() {
   var map1 map[string]int = make(map[string]int)
   map1["one"] = 1
   fmt.Println(map1)

   var map2 map[string]int = map[string]int{"1":1}
   map["2"] = 2
   fmt.Println(map2)
   
}

如何获取一个整数的各个位上的数字

package main

import "fmt"

func main() {
    var temp_data int = 123
    fmt.Println(temp_data/100%10)  // 获取百位上的数字
    fmt.Println(temp_data/10%10)  // 获取十位上的数字
    fmt.Println(temp_data/1%10)  // 获取个位上的数字

}

go语言中的算数运算符号/关系运算符/逻辑运算符/位运算符

GO语言中,有很多值得学习的运算符,最基本的就是算数运算符,就是加减乘除取余,然而还有其它的有意思的运算符哦,一起来看看吧,注释写的很详细哦。
package main
 
import "fmt"
 
func main() {
    //算数运算符
    a := 10
    b := 20
    fmt.Println(a + b)
    fmt.Println(a - b)
    fmt.Println(a*b, a/b, a%b)

    a++
    b++
    fmt.Println(a)
    fmt.Println(b)

    //关系运算符
    fmt.Println(a == b, a >= b, a <= b, a != b) //真就为true,假就是false,bool类型

    //逻辑运算符 &&与 ||或 !非(就是取反)
    fmt.Println(10 > 5 && 5 > 2) //两边均为true结果就是true
    fmt.Println(10 > 4 || 5 > 6) //至少有一个为true就是true
    fmt.Println(!(10 > 5))       //!运算符,把true与false互换

    //4运算符,对整数在内存中的二进制位进行操作
    aa := 1              //二进制001
    bb := 5              //二进制101
    fmt.Println(aa & bb) //参与运算的两数各对应的二进位相与(两位均为一才为1)
    //如   001
    //     101
    //结果为001
    //1对1为1,0与0为0,1对0为0,所以结果为001,转换为10进制就是1
    fmt.Println(aa | bb) //二进位相或,两位有一个为1就为1,所以结果为101,10进制5
    fmt.Println(aa ^ bb) //相异或,当对应二进位相异时结果为1(两位不一样则为1),100,10进制4
    fmt.Println(1 << 2)  //左移n位就是乘以2的n次方,“a<<b”就是把a的各二进位全部左移b位,高位丢弃,低位补0,结果为100,就是4
    fmt.Println(4 >> 2)  //右移n位就是除以2的n次方,“a>>b”就是把a的各二进位全部右移b位,100右移2为就是1
 
}

判定空值

<1> "" 空字符串

// 这种判断为空的方式,适用于你知道你要判断的这个东西是字符串类型的。
var test string
if test == "" {
   fmt.Println("test is empty")
}

<2>nil

  nil一般是判断结构体的指针是否为空
  type test struct {
     name string
     password string
  }
  
  func main() {
      var data *test
      if data == nil {
         fmt.Println(" struct data is empty)
      }
  }

<3> len(x) == 0

 // 这种方式,一般是用来判断数组,切片这种数据类型的。
 // 如果其中的元素的个数是0,那么这个变量就可以认为是空。
 
 func main() {
     var test []string
     if len(test) == 0 {
        fmt.Println("[]string test is empty")
     }
 
 }

go中的全局变量和局部变量

在golang中,全局变量的生命周期属于整个包,这个和C不同,因为C语言没有包的概念。

在golang的main包中,main包定义的全局变量无法被其他包引用。

如果想使用全局变量,建议在其他包中定义并进行引用。

在golang中,局部变量的生命周期属于花括号{}之内,这和C语言一致。

还有,在声明了一个全局变量之后,如果再声明一个同名的局部变量,该同名局部变量的生命周期为花括号{}内。

在其他语言中,局部变量会得到明显确认,但golang中,有种声明局部变量的语法糖 := 。

如下面例子:
var p int   // 这里声明了一个全局变量p

// 定义了test()函数,输入一个整数int,得到一个int+1
func test(i int) (int, error) {
    return i + 1, nil
}

func main() {
    p, err := test(4)  // 在main()函数中,得到了一个 局部变量p
    if err != nil {
        log.Fatal(err)
    }
}

结构体的定义 && 结构体变量

结构体和结构体变量的区别和联系

1 结构体是自定义的一种数据类型,代表一类事物。
2 结构体变量(实例)是具体的,实际的,代表一个具体变量。

以上的解释,其实我们可以理解为结构体就像是python中的类class,
而结构体变量就是我们根据这个类class,而实例出来的一个实例化对象。
我们看一个根据这个结构体(类class),实例出无数个对象。

如何自定义一个结构体

基本语法是:
  type 结构体名称 struct {
      field1 type
      field2 type
      field3 type
      ....   ....
  }
  结构体中的field的数量是没有限制的
  
  demo:
  type Student struct {
      Name string
      Age int 
      Score float32
  }
  
  以上我们自定义了一个Student的结构体(或者称为一个类)
  可以看到,结构体的名称和field的名称,首字母都是大写的。
  而且行与行之间是没有逗号分隔的。
   

field/字段/属性

从概念上来说,结构体字段=属性=field
字段是结构体的一个组成部分,一般是基本数据类型/数组,也可以是引用类型。

根据一个结构体创建一个结构体变量的时候(也就是实例化一个对象),如果没有给field赋值,则会对应一个初始值。
字符串的初始值是“”,int的初始值是0float的初始值是0.0,
指针,slice map的初始值都是nil,及还没分配空间。

实战demo

package main

import "fmt"

// 自定义一个结构体Person
type Person strct {
     Name string
     Age int 
     Scores [5]float64
     ptr *int 
     slice []int
     map1 map[string]string
}


func main() {
   // 定义结构体变量
   var p1 Person
   fmt.Println(p1)
   if p1.ptr == nil {
      fmt.Println("ok1")
   }
   if p1.slice == nil {
      fmt.Println("ok2")
   }
   if p1.map1 == nil {
      fmt.Println("ok3")
   }
   // 使用 slice,一定要 make
   p1.slice = make([]int, 10)
   p1.slice[0] = 100 // ok
   // 使用 map, 一定要 make
   p1.map1 = make(map[string]string)
   p1.map1["key1"] = "tom~"
   fmt.Println(p1)
}
// 输出结果是
{ 0 [0 0 0 0 0] <nil> [] map[]}
ok1
ok2
ok3
{ 0 [0 0 0 0 0] <nil> [100 0 0 0 0 0 0 0 0 0] map[key1:tom~]}

不同的结构体变量的字段field是独立的,互不影响,一个结构体变量字段的更改,不会影响另一个结构体变量

package main
 
import "fmt"

// 自定义一个结构体Monster
type Monster struct{
   Name string
   Age int
}
 
func main() {
   // 不同结构体变量的字段是独立,互不影响,一个结构体变量字段的更改,不影响另外一个, 结构体是值类型
   var monster1 Monster
   monster1.Name = "牛魔王"
   monster1.Age = 500
   
   monster2 := monster1 // 结构体是值类型,默认为值拷贝
   monster2.Name = "青牛精"
   fmt.Println("monster1=", monster1) // monster1= {牛魔王 500}
   fmt.Println("monster2=", monster2) // monster2= {青牛精 500}
}

go语言中的切片slice

 关于对slice的操作,主要有以下几种操作
 输出slice中指定位置(这里的位置类似于python中的index,都是从0开始)的元素。
 遍历切片中的原素,输出index和元素。
 复制切片
 修改切片中的元素
 在切片中添加元素
 用for循环打印整个元素
 
package main

import "fmt"


func main() {
  //1,初始化一个切片,打印切片中的第1个元素
  // 打印的方式和python一样,用[],其中的index从0开始
  var food = []string{"苹果", "橘子", "香蕉", "西瓜", "大鸭梨"}
  fmt.Println(food[1])
  
  //2,遍历切片元素,在屏幕输出“序号和元素”
  for id, name := range food {
     fmt.Println(id)
     fmt.Println(name)
  }
  
  //3,复制一个切片并输出
  var food2 = food[:]
  fmt.Println(food2)
  food3 := make([]string, 6)
  copy(food3, food2)
  fmt.Println(food3)
  
  //4,修改切片中的一个元素
  // 修改的方式简单利索,直接修改即可
  food3[0] = "哈密瓜"
  fmt.Println(food3)
  
  //5,为切片添加元素
  // 在slice中添加元素的方式也很简单,和python中的一样,用append()函数
  food = append(food, "大西红柿")
  fmt.Println(food)
  
  //6,打印前3个元素和用for循环打印整个元素
  fmt.Println(food[:3])
  
  // 如果想遍历打印slice中的元素,而不打印index,则可以写成for _, name := range slice_name {}
  for _, name := range food {
     fmt.Println(name)
  }
}

go打印变量的类型

图片.png