Go:学习笔记兼吐槽(1)

Go:学习笔记兼吐槽(2)

Go:学习笔记兼吐槽(3)


数组

Golang 中,数组是值类型。

数组的声明

var arr [10]int

数组的初始化

var arr1 [3]int = [3]int{1, 2, 3}
var arr2 = [3]int{4, 5, 6}
var arr3 = [...]int{7, 8, 9}
var arr4 = [...]int{1: 100, 2: 200, 3: 300}

用 for-range 遍历数组

基本语法:

for index, value := range 数组变量{
}

其中:index 为数组下标,value 是该下标位置的值。

长度是数组类型的一部分

长度是数组类型的一部分,就是说数组不可以脱离长度而存在。听起来不太明白,我们来看下面的一个示例就明白了,这真的是一个大坑。

假设,我们现在要写一个排序函数,C# 中,我们会这样定义:

public void Sort(int[] array)
{
}

但是,在 Golang 中,这是不行的。

func main() {
    var arr [3]int = [3]int{1, 2, 3}
    Sort(arr)
} func Sort(array []int){
}

Sort(arr) 这句编译就会报错:cannot use arr (type [3]int) as type []int in argument to Sort。因为 Sort 函数的参数 array []int 是一个切片,不是数组,将数组作为参数传给 Sort 就会报类型不匹配。

如果一定需要以数组作为参数传递,Sort 的参数必须定义成数组,就是带上长度:

func Sort(array [3]int){
}

这么定义这函数还有啥用?吐槽一万字…
虽然有切片可以用来实现我们的功能,但是,数组就变得有点鸡肋了。

切片 slice

切片是引用类型,类似于 C# 中的 list 。内部维护一个数组,当追加元素超出切片容量时,切片自动扩容。(跟 list 是一样的机制。)

切片的声明

var arr []int

切片的使用

//方法一:
var arr1 [5]int = [5]int{1, 2, 3, 4, 5}
slice1 := arr1[1: 3]    //这里的使用跟 Python 很像 //方法二:
var slice2 []int = make([]int, 5, 10) //方法三:
var slice3 []int = []int{1, 2, 3, 4, 5}

使用 make 初始化切片,make 的三个参数依次为:切片数据类型,切片长度,切片容量。

给切片追加元素

//方法一:追加一个或多个同类型
var slice1 []int = make([]int, 5, 10)
slice1 = append(slice1, 100, 200)
fmt.Printf("%v\n", slice1) //方法二:追加切片(只能是切片,不可以是数组)
var slice2 []int = []int{1, 2, 3, 4, 5}
slice1 = append(slice1, slice2...)    // 三个点不能少
fmt.Printf("%v", slice1)

append 函数也很搞笑,其返回值必须赋值给一个切片,否则编译都过不了。如果一个切片调用 append 追加元素后,又赋值给了自己(我们一般也是这么用的),则切片的地址不会发生改变(除非发生了扩容)。如果 切片 1 调用 append 后赋值给了 切片 2,则 切片 1 保持未追加前的原样不变,另生成一个新的切片赋给 切片 2

示例:

var slice1 []int = make([]int, 5, 10)
fmt.Printf("%v %p\n", slice1, &slice1)    // [0 0 0 0 0] 0xc000004460 slice1 = append(slice1, 100)
fmt.Printf("%v %p\n", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460 slice2 := append(slice1, 200)
fmt.Printf("%v %p\n", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460
fmt.Printf("%v %p\n", slice2, &slice2)    // [0 0 0 0 0 100 200] 0xc0000044e0

映射 map

就是字典。

map 的声明

var m map[int]string

map 的使用

// 方式一:使用 make 函数
m := make(map[int]string, 10) // 方式二:直接赋值
m := map[int]string{
    1: "张三",
    2: "李四",
}

make 方法的第一个参数是 map 的数据类型,第二个参数是初始容量。

注意,如果是方式二直接赋值,最后一个 key-value 后面也要加逗号。

删除元素

delete(map, key)

参数:

  • map:要删除元素的 map
  • key:要删除的 key,当 key 在 map 中不存在时,不进行任何操作,也不报错。

Golang 中 map 没有类似其他语言中的 clear 方法,如果要一次性删除全部元素,可遍历 map 逐一删除,或者重新 make 一下使其指向一个新的内存空间。

查找元素

val, finded := m[1]
if finded{
    fmt.Println(val)
}

遍历元素

只能用 for-range 遍历

for k, v := range m{
    fmt.Printf("%v: %v\n", k, v)
}

结构体 struct

  • Golang 中没有类(class),Go 中的结构体(struct)和其他语言中的类有同等的地位。可以理解为 Golang 是基于 struct 来实现面向对象。
  • 结构体是值类型。结构体的所有字段在内存中是连续的。

结构体的声明

type 结构体名称 struct{
    field1 type
    field2 type
}

结构体的使用

type Person struct{
    Name string
    Age int
} // 方式一:
p1 := Person{}
p1.Name = "Tom"
p1.Age = 10 // 方式二
p2 := Person{"Jerry", 5} // 方式三
p3 := Person{Name: "张三", Age: 30}
// 或
p3 := Person{
Name: "张三", 
Age: 30,        // 注意这里要加逗号,否则会被默认加上分号
}

结构体指针

// 方式一:
var person1 *Person = new(Person)
(*person1).Name = "Tom"
(*person1).Age = 10
fmt.Println(*person1) // 方式二:
person2 := new(Person)
person2.Name = "Tom"
person2.Age = 10
fmt.Println(*person2) // 方式三:
var person3 *Person = &Person{"Jerry", 5}
fmt.Println(*person3)

这三种方式定义的都是结构体指针,因为是指针,所以给字段赋值的标准方式应该是方式一的写法,但是 Go 的设计者为了程序员使用方便,给出了一个语法糖,使 (*person1).Name = "Tom" 简化为 person1.Name = "Tom",即方式二的写法,编译时,会自动加上取值运算。而方式三的写法可以直接赋值。

结构体标签

struct 的每个字段上可以定义一个标签(tag),该标签可以通过反射机制获取,最常见的使用场景就是序列化和反序列化。

type Person struct{
    Name string `json:"name"`
    Age int `json:"age"`
} p := Person{"张三", 30}
jsonStr, err := json.Marshal(p)
if err == nil {
    fmt.Println(string(jsonStr)) // {"name":"张三","age":30}
}

自定义数据类型

为了简化数据类型定义,Golang 支持自定义数据类型。

基本语法:

type 自定义数据类型名 数据类型  // 相当于起了一个别名

示例:

type myint int  //这时 myint 就等价于 int,但是 Go 会认为他们还是两个类型
type mySum func(int, int) int  //这时 mySum 就等价于一个函数类型

自定义数据类型跟原类型虽然在我们的理解上是一样的,但是 Golang 会认为它们是两种不同的数据类型。这导致这两种类型是无法直接进行比较的,必须强转。

Go:学习笔记兼吐槽(3)的更多相关文章

  1. Go:学习笔记兼吐槽(2)

    Go:学习笔记兼吐槽(1) Go:学习笔记兼吐槽(2) Go:学习笔记兼吐槽(3) 基本数据类型和string之间的转换 (1) 基本类型转string 使用 fmt.Sprintf(“%参数”, 表 ...

  2. Go:学习笔记兼吐槽(1)

      Go:学习笔记兼吐槽(1) Go:学习笔记兼吐槽(2) Go:学习笔记兼吐槽(3) 自动添加分号 在很多其他的编程语言中,每一行代码的结尾都必须有分号(假设一行中只有一句代码),Golang 的开 ...

  3. Salesforce学习笔记之吐槽

    迄今感到的几个不方便 1. SOQL里没有SELECT * ,只好根据参考手册和用vs code的一个插件Schema Explorer来辅助生成SELECT语句. 2. SOQL不支持注释,Deve ...

  4. R语言学习笔记之: 论如何正确把EXCEL文件喂给R处理

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html ---- 前言: 应用背景兼吐槽 继续延续之前每个月至少一次更新博客,归纳总结学习心得好习惯. ...

  5. Android学习笔记之短信验证码的获取和读取

    PS:最近很多事情都拖拖拉拉的..都什么办事效率啊!!! 还得吐槽一下移动运营商,验证码超过五次的时候,直接把我的手机号封闭.真是受够了. 学习笔记: 1.Android之如何获取短信验证码. 2.如 ...

  6. 【Stage3D学习笔记续】真正的3D世界(一):透视矩阵

    如果各位看官跟着我的学习笔记一路看过来的话,一定会吐槽我的,这都是什么3D啊?从头到尾整个都是在使用GPU绘制一堆2D图像而已,的确,之前我们一直使用正交矩阵利用GPU加速来实现2D世界的展示,算不上 ...

  7. Web Service学习笔记(webservice、soap、wsdl、jws详细分析)

    Web Service概述 Web Service的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API ...

  8. Web Service学习笔记

    Web Service概述 Web Service的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API ...

  9. Web Service学习笔记(webservice、soap、wsdl、jws详细分析) (转)

    Web Service概述 Web Service的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API ...

随机推荐

  1. javascript 用函数语句和表达式定义函数的区别详解

    通常我们会看到以下两种定义函数的方式: // 函数语句 function fn(str) { console.log(str); }; // 表达式定义 var fnx=function(str) { ...

  2. HTML 返回顶部

    每次看淘宝,看微信,都回有回到顶部的小logo,小图标,或者双击返回顶部.所以就学习了如何返回顶部的操作,一开始是联想html中的链接描点,在开头出设置个标签,下面点击另外一个标志回去.有三种觉得比较 ...

  3. 填坑!!!virtualenv 中 nginx + uwsgi 部署 django

    一.为什么会有这篇文章 第一次接触 uwsgi 和 nginx ,这个环境搭建,踩了太多坑,现在记录下来,让后来者少走弯路. 本来在 Ubuntu14.04 上 搭建好了环境,然后到 centos7. ...

  4. Asp.Net MVC 中JS通过ajaxfileupload上传图片获取身份证姓名、生日、家庭住址等详细信息

    客户要求用身份证图片上传获取身份证的详细信息就下来研究了一下(现在的客户真的懒 身份证信息都懒得输入了哈哈...),经过慢慢研究,果然皇天不负有心人搞出来了.这个借助的是腾讯的一个SKD  腾讯优图云 ...

  5. 分布式架构真正适用于大型互联网项目的架构! dubbo+zookeeper+springmvc+mybatis+shiro+redis

     分类: 分布式技术(3)    目录(?)[+]   平台简介 Jeesz是一个分布式的框架,提供项目模块化.服务化.热插拔的思想,高度封装安全性的Java EE快速开发平台. Jeesz本身集成D ...

  6. 玩转zookeeper命令

    zkCli 是 zookeeper 原生的与 zk服务群连接的客户端的程序. 1.如何使用zkCli,sh 连接server 与参数 2.zkCli 下的增删查改指令 与 配额 quota 1.如何使 ...

  7. 基于opencv3.0下的运动车辆识别

    在opencv的初等应用上,对运动物体的识别主要有帧差或背景差两种方式. 帧差法主要的原理是当前帧与前一帧作差取绝对值: 背景差主要的原理是当前帧与背景帧作差取绝对值: 在识别运动车辆上主要需要以下9 ...

  8. Android开发环境的配置2017.05.27

    关于配置Android开发环境请参考此链接:http://blog.chinaunix.net/uid-25434387-id-461933.html

  9. 用secureCRT连接虚拟机中的Ubuntu系统,出现“远程主机拒绝连接”错误

    因为我的Ubuntu中未安装ssh服务,终端下运行命令: sudo apt-get install openssh-server 之后重启一下sshd服务: sudo service sshd res ...

  10. 学习ASP.NET Core Razor 编程系列十——添加新字段

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...