Go语言基础(1)

Meteor_hy · · 774 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go语言基础(1)

环境配置

(base) yuanjicai@localhost ~ % tail -4 .zprofile
export GOROOT="/usr/local/go"
export GOPATH="/Users/yuanjicai/go"
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
(base) yuanjicai@localhost ~ %

GOROOT 是安装go开发包的路径

工作区GOPATH

​ 1) src/ 存储GoLang源代码程序

​ 2) pkg/

​ 3) bin/ 在执行go install时,它先编译源代码得到可执行文件,然后将可执行文件移动到GOPATH的bin目录下。

(base) yuanjicai@localhost ~ % ls $GOPATH
bin pkg src

常用命令

go build [-o DestFileName]

go run

go install

常见的路径组织方式:

src/project_doman_name/userName/projectName/moduleName

src/domain_name/departmentName/projectName/moduleName

跨平台编译

Mac 下编译 Linux 和 Windows平台 64位 可执行程序:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Linux 下编译 Mac 和 Windows 平台64位可执行程序:

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

Windows下编译Mac平台64位可执行程序:

SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build

第一个Go程序

package main
import "fmt"
func main() {
    fmt.Println("Hello World")
}

说明:

package 声明包名

​ 如果是main包,编译时会编译成可执行文件;

​ 如果是main包,必须有 func main() {} 函数;main函数没有参数,也没有返回值 ;

函数外只能放置标识符(变量/常量/函数/类型)的声明

​ 标识符: 程序员定义的具有特殊意义的词, 如变量名、常量名、函数名等等

​ 关键字: 是指编程语言中预先定义好的具有特殊含义的标识符

Go语言中有25个关键字

  break    default   func     interface  select
  case     defer    go      map     struct
  chan     else     goto     package   switch
  const    fallthrough if      range    type
  continue   for     import    return    var

Go语言中还有37个保留字

Constants:  true false iota nil
Types:  int int8 int16 int32 int64  
        uint uint8 uint16 uint32 uint64 uintptr
        float32 float64 complex128 complex64
        bool byte rune string error
Functions:  make len cap new append copy close delete
        complex real imag
        panic recover

变量

Go语言的变量声明格式为:

var 变量名 变量类型

批量变量声明

var (
  a string
  b int
  c bool
  d float32
)

可在声明变量的时候为其指定初始值

var 变量名 类型 = 表达式

在函数内部,可以使用更简略的 := 方式声明并初始化变量

func main() {
    n := 10
  m := 200 // 此处声明局部变量m
    fmt.Println(m, n)
}

匿名变量用一个下划线_表示,

func foo() (int, string) {
    return 10, "Q1mi"
}

func main() {
    x, _ := foo()
    _, y := foo()
    fmt.Println("x=", x)
    fmt.Println("y=", y)
}

说明:

​ 1) :=不能使用在函数外。

​ 2) _多用于占位,表示忽略值。

局部变量声明后 必须使用,否则编译无法顺利通过。同样import 包之后也必须使用,否则编译无法顺利通过。

常量

常量的声明和变量声明非常类似,只是把var换成了const,常量在定义的时候必须赋值。

const pi = 3.1415
const e = 2.7182
const (
  pi = 3.1415
  e = 2.7182
)

iota是go语言的常量计数器,只能在常量的表达式中使用

iota在const关键字出现时将被重置为0,const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。

使用_跳过某些值

const (
        n1 = iota //0
        n2    //1
        _
        n4    //3
    )

数据类型

Go语言中有丰富的数据类型,除了基本的整型、浮点型、布尔型、字符串外,还有数组、切片、结构体、函数、map、通道(channel)等。Go 语言的基本类型和其他语言大同小异。

整型

整型分为以下两个大类: 按长度分为:int8、int16、int32、int64 对应的无符号整型:uint8、uint16、uint32、uint64

其中,uint8就是我们熟知的byte型,int16对应C语言中的short型,int64对应C语言中的long型。

类型 描述
uint8 无符号 8位整型 (0 到 255)
uint16 无符号 16位整型 (0 到 65535)
uint32 无符号 32位整型 (0 到 4294967295)
uint64 无符号 64位整型 (0 到 18446744073709551615)
int8 有符号 8位整型 (-128 到 127)
int16 有符号 16位整型 (-32768 到 32767)
int32 有符号 32位整型 (-2147483648 到 2147483647)
int64 有符号 64位整型 (-9223372036854775808 到 9223372036854775807)

特殊整型

类型 描述
uint 32位操作系统上就是uint32,64位操作系统上就是uint64
int 32位操作系统上就是int32,64位操作系统上就是int64
uintptr 无符号整型,用于存放一个指针

注意: 在使用int和 uint类型时,不能假定它是32位或64位的整型,而是考虑int和uint可能在不同平台上的差异。

注意事项 获取对象的长度的内建len()函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以用int来表示。在涉及到二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用int和 uint

package main

import "fmt"
import "math"

func main(){

    var a int = 10
    fmt.Printf("%d \n", a) // 10
    fmt.Printf("%b \n", a) // 1010 占位符%b表示二进制

    var b int = 077
    fmt.Printf("%o \n", b) // 77

    var c int = 0xff
    fmt.Printf("%x \n", c) // ff
    fmt.Printf("%X \n", c) // FF
  fmt.Printf("%.2f\n", math.Pi)
}

布尔型

Go语言中以bool类型进行声明布尔型数据,布尔型数据只有true(真)和false(假)两个值。

注意:

  1. 布尔类型变量的默认值为false。
  2. Go 语言中不允许将整型强制转换为布尔型.
  3. 布尔型无法参与数值运算,也无法与其他类型进行转换。

浮点型

Go语言支持两种浮点型数:float32和float64。这两种浮点型数据格式遵循IEEE 754标准: float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32。 float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64。

浮点数输出时,可以使用fmt包,并配合动词%f,默认使用float64

复数

complex64和complex128
var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Println(c1)
fmt.Println(c2)

复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位

字符串

Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。 Go 语言里的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符。Go 语言如果使用单引号,表示字符。

字符串转义符

Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。

转义符 含义
\r 回车符(返回行首)
\n 换行符(直接跳到下一行的同列位置)
\t 制表符
\' 单引号
\" 双引号
\ 反斜杠
多行字符串

Go语言中要定义一个多行字符串时,就必须使用反引号字符

字符串的常用操作
方法 介绍
len(str) 求长度
+或fmt.Sprintf 拼接字符串
strings.Split 分割
strings.contains 判断是否包含
strings.HasPrefix,strings.HasSuffix 前缀/后缀判断
strings.Index(),strings.LastIndex() 子串出现的位置
strings.Join(a[]string, sep string) join操作

例:

var str1 string = "aaaa bbbb ccc"
var str2 string = "111 222 333"
fmt.Print(len(str1), len(str2), "\n")
str3 := fmt.Sprintf("%s %s", str1, str2)
fmt.Println(str3)
fmt.Println(strings.Split(str3, " "))
fmt.Println(strings.Contains(str3, "ccc"))
fmt.Println(strings.HasPrefix(str3,"a"))
fmt.Println(strings.HasSuffix(str3,"4"))
fmt.Println(strings.Index(str3, "c"))
fmt.Println(strings.LastIndex(str3,"c"))

elem1 := strings.Split(str3, " ")
fmt.Println(strings.Join(elem1, "_"))

输出:

14 11
aaaa bbbb ccc 111 222 333
[aaaa bbbb ccc 111 222 333]
true
true
false
11
13
aaaa_bbbb__ccc_111_222_333

字符型

Go 语言的字符有以下两种:

  1. uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。
  2. rune类型,代表一个 UTF-8字符。

当需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32。

Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode 的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。

例:

str2 := "白萝卜"
str3 := []rune(str2) //把字符串转换成一个rune类型的列表
str3[0] = '红'
fmt.Println(string(str3))

输出:

红萝卜

类型转换

强制类型转换的基本语法如下:

T(表达式)

其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.

整型、浮点型可以相互转换

流程控制

分支语句--if

语法如下:

if 表达式1 {
  分支1
} else if 表达式2 {
  分支2
} else{
  分支3
}

例:

func ifDemo() {
    if score := 65; score >= 90 {
        fmt.Println("A")
    } else if score > 75 {
        fmt.Println("B")
    } else {
        fmt.Println("C")
    }
}

说明:在 if 表达式之前添加一个执行语句,再根据变量值进行判断

分支语句--switch

使用switch语句可方便地对大量的值进行条件判断

func switchDemo1() {
    finger := 3
    switch finger {
    case 1:
        fmt.Println("大拇指")
    case 2:
        fmt.Println("食指")
    case 3:
        fmt.Println("中指")
    case 4:
        fmt.Println("无名指")
    case 5:
        fmt.Println("小拇指")
    default:
        fmt.Println("无效的输入!")
    }
}

一个分支可以有多个值,多个case值中间使用英文逗号分隔。

func switchDemo2() {
    age := 30
    switch {
    case age < 25:
        fmt.Println("好好学习吧")
    case age > 25 && age < 35:
        fmt.Println("好好工作吧")
    case age > 60:
        fmt.Println("好好享受吧")
    default:
        fmt.Println("活着真好")
    }
}

fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。

func switchDemo3() {
    s := "a"
    switch {
    case s == "a":
        fmt.Println("a")
        fallthrough
    case s == "b":
        fmt.Println("b")
    case s == "c":
        fmt.Println("c")
    default:
        fmt.Println("...")
    }
}

输出:

a
b

循环语句

for 初始语句;条件表达式;结束语句{

  循环体语句

}

func forDemo() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }
}

func forDemo2() {
    i := 0
    for ; i < 10; i++ {
        fmt.Println(i)
    }
}

func forDemo3() {
    i := 0
    for i < 10 {
        fmt.Println(i)
        i++
    }
}

循环语句--for range

Go语言中可以使用for range遍历数组、切片、字符串、map 及通道(channel)。 通过for range遍历的返回值有以下规律:

  1. 数组、切片、字符串返回索引和值。
  2. map返回键和值。
  3. 通道(channel)只返回通道内的值

字符串默认返回索引和值

for i, v := range str1 {
    fmt.Printf("%d %c \n", i, v)
}

跳转语句--goto

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程。

for i:=1; i<10; i++ {
    if i==5 {
        goto xx
    }
    fmt.Println(i)
}
xx:
    fmt.Println("over")

循环控制关键字--break、continue

func breakDemo1() {
    var breakFlag bool
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if j == 2 {
                // 设置退出标签
                breakFlag = true
                break
            }
            fmt.Printf("%v-%v\n", i, j)
        }
        // 外层for循环判断
        if breakFlag {
            break
        }
    }
}

Go语言运算符

算术运算

+ 相加
- 相减
* 相乘
/ 相除
% 求余

注意: ++(自增)和--(自减)在Go语言中是单独的语句,并不是运算符。

比较运算

== 检查两个值是否相等,如果相等返回 True 否则返回 False。
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False。
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

逻辑运算

&& 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。
|| 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。
! 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。

位运算

& 参与运算的两数各对应的二进位相与。 (两位均为1才为1)
| 参与运算的两数各对应的二进位相或。 (两位有一个为1就为1)
^ 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1)
<< 左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。
>> 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。

&记忆方式: 很容易理解(真真才为真,相当于&&必须两个条件为真时才为真).

用途:

​ 1) 一般用于位清零操作,和取位值操作 ;

​ 2) 保留指定位;

​ 3) 取一个数中某些指定位

例:0xD2 &= ~(0xf << 4) 高四位清0

a & b == b 说明: a>=b

a & 1 == 0 说明 a 为偶数 ; 反之为奇数

|记忆方式: 很容易理解(假假才为假,相当于||必须两个条件为假时才为假,任何有为真的都是返回真)

用途:

​ 1) 一般用于位段设置值的操作;

​ 2) 按位或运算常用来对一个数据的某些位定值为1

异或: 相同时为0,不同时为1

用途:

​ 1) 使特定位翻转;

​ 2) 与0相“异或”,保留原值;

​ 3) 交换两个值,不用临时变量;

a ^ 0xf 实现低四位翻转 (任何数与全1相异或,都可以实现翻转)

    a := 3
    b := 4
    fmt.Println(a^0, b^0)  // 保持原值不变 (任何数与0异或,保持原值不变)
    fmt.Println(a^b^a)    // 输出4
    fmt.Println(a^b^b)    // 输出3
    a=a^b
    b=b^a
    a=a^b
    fmt.Printf("a=%d \t b=%d\n", a, b)  // a=4 ; b=3        不使用临时变量,实现两个变量值的交换

赋值运算

= 简单的赋值运算符,将一个表达式的值赋给一个左值
+= 相加后再赋值
-= 相减后再赋值
*= 相乘后再赋值
/= 相除后再赋值
%= 求余后再赋值
<<= 左移后赋值
>>= 右移后赋值
&= 按位与后赋值
|= 按位或后赋值
^= 按位异或后赋值

数组

在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。

基本语法:

var 数组名 [元素数量]T

例:

var a [3]int 

例:

var cityArray = [3]string{"北京", "上海", "深圳"}
var numArray = [...]int{1, 2}
a := [...]int{1: 1, 3: 5}

例:

cities := [...]string{"北京", "上海", "深圳"}
for i, v := range cities{
    fmt.Printf("index: %d\t value: %s\n", i, v)
}
for i:=0; i<len(cities); i++ {
    fmt.Println(cities[i])
}

例:

cities2 := [2][3]string{
    {"北京","上海","深圳"},
    {"甘肃","青海","新疆"},
}
for _, v1 := range cities2{
    for _, v2 := range v1 {
        fmt.Printf("%s \t",v2)
    }
    fmt.Println()
}

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值

数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。

[n]*T表示指针数组,*[n]T表示数组指针

切片(Slice)

切片是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。

切片是一个引用类型,它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数据集合。

声明切片类型的基本语法如下:

var name []T

说明:

​ 1) name:表示变量名

​ 2) T:表示切片中的元素类型

例:

a := [5]int{1, 2, 3, 4, 5}
s := a[1:3]         // s := a[low:high]     s的值是:[2 3]
t := a[1:3:5]
fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t))     //t:[2 3] len(t):2 cap(t):4

var d = []bool{false, true}
fmt.Println(d == nil)       //输出false

切片拥有自己的长度和容量,可以通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量

切片表达式从字符串、数组、指向数组或切片的指针构造子字符串或切片。它有两种变体:一种指定low和high两个索引界限值的简单的形式,另一种是除了low和high索引界限值外还指定容量的完整的形式。

例:

a1 := [5]int{1,2,3,4,5}
s1 := a1[1:3]   //[2 3]
s2 := a1[:3]        //[1 2 3]
s3 := a1[3:]        //[4 5]
fmt.Println(s1, s2, s3)

长度=high-low,容量等于得到的切片的底层数组的容量。对于数组或字符串,如果0 &lt;= low &lt;= high &lt;= len(a),则索引合法,否则就会索引越界(out of range)。如果索引在运行时超出范围,就会发生运行时panic

完整切片表达式如下:

a[low : high : max]

注: 切片a不能是字符串

使用make()函数构造切片

如果需要动态的创建一个切片,需要使用内置的make()函数,格式如下

make([]T, size, cap)

切片的本质

Go语言基础(1)

Go语言基础(1)

检查切片是否为空

要检查切片是否为空,请始终使用len(s) == 0来判断,而不应该使用s == nil

比较运算

切片之间是不能比较

var s1 []int     //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{}    //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil

切片的遍历

切片的遍历方式和数组是一致的,支持索引遍历和for range遍历

切片添加元素

slice append可以为切片动态添加元素。 可以一次添加一个元素,可以添加多个元素,也可以添加另一个切片中的元素

s4 := []string{"beijing", "shanghai", "shenzhen"}
s4 = append(s4, "qinghai")
fmt.Println(s4)
fmt.Printf("%d %d \n", len(s4), cap(s4))
s5 := []string{"xi an", "hangzhou"}
s4 = append(s4, s5...)
fmt.Println(s4)

切片的扩容策略

​ 1) 首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。

​ 2) 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap),

​ 3) 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)

​ 4) 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)。

需要注意的是,切片扩容还会根据切片中元素的类型不同而做不同的处理,比如int和string类型的处理方式就不一样。

切片值的修改

    a := []int{1, 2, 3, 4, 5}
    b := a

由于切片是引用类型,所以a和b其实都指向了同一块内存地址。修改b的同时a的值也会发生变化。

切片复制

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中, copy()函数的使用格式如下:

copy(destSlice, srcSlice []T)

说明:

​ 1) srcSlice: 数据来源切片

​ 2) destSlice: 目标切片

s6 := make([]string, 7, 7)
copy(s6, s4)
fmt.Println(s6)

删除切片成员

Go语言中并没有删除切片元素的专用方法,可以使用切片本身的特性来删除元素。例, 删除下标为1的成员

s4 = append(s4[:1], s4[2:]...)
fmt.Println(s4)
fmt.Printf("%d", cap(s4))

映射Map

Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。

map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用

map的定义语法如下:

map [KeyType] ValueType

说明:

​ 1) KeyType:表示键的类型。

​ 2) ValueType:表示键对应的值的类型。

map类型的变量默认初始值为nil,需要使用make()函数来分配内存。语法为:

make(map[KeyType]ValueType, [cap])

其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。

例:

    scoreMap := make(map[string]int, 8)
    scoreMap["张三"] = 90
    scoreMap["小明"] = 100

Go语言中有个判断map中键是否存在的特殊写法,格式如下:

value, ok := map[key]

遍历map

Go语言中使用for range遍历map。注意: 遍历map时的元素顺序与添加键值对的顺序无关。

删除map中键值对

使用delete()内建函数从map中删除一组键值对,delete()函数的格式如下:

delete(map, key)

说明:

​ 1) map:表示要删除键值对的map

​ 2) key:表示要删除的键值对的键

指针

&(取地址)和*(根据地址取值)

例:

b := &a

Go语言基础(1)

总结: 取地址操作符&和取值操作符是一对互补操作符,&取出地址,根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

​ 1) 对变量进行取地址(&)操作,可以获得这个变量的指针变量。

​ 2) 指针变量的值是指针地址。

​ 3) 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值

分配内存

Go语言中new和make是内建的两个函数,主要用来分配内存。

new是一个内置的函数,它的函数签名如下:

func new(Type) *Type

说明:

​ 1) Type表示类型,new函数只接受一个参数,这个参数是一个类型

​ 2) *Type表示类型指针,new函数返回一个指向该类型内存地址的指针。

​ 3) new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值

例: var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。应该按照如下方式使用内置的new函数对a进行初始化之后就可以正常对其赋值了:

    var a *int
    a = new(int)
    *a = 10

make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

func make(t Type, size ...IntegerType) Type

make函数是无可替代的,在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。

newmake的区别

  1. 二者都是用来做内存分配的。
  2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
  3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针

本内容仅为个人学习Go的笔记,部分内容属于摘抄整理,若遇喷子敬请口下留情.


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:Meteor_hy

查看原文:Go语言基础(1)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

774 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传