自定义类型

两种用户定义的类型

  • 结构类型
  • 基于一个已有的类型,将其作为新类型的类型说明

结构体变量定义和初始化

type struct_variable_type struct {
member definition
member definition
...
member definition
}

一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:

variable_name := structure_variable_type {value1, value2...valuen}
// 或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}

实例

package main

import "fmt"

type Person struct {
name string
sex byte
age int
} func main() { // 顺序初始化,必须全部初始化完整
var person Person = Person{"wang", 'f', }
fmt.Println(person) // 部分初始化
person1 := Person{name: "zhao", sex: 'm'}
fmt.Println(person1.name)
}

赋值、比较和传参

使用.索引成员变量

    // 部分初始化
person1 := Person{name: "zhao", sex: 'm'}
fmt.Println(person1.name) person1.name = "li"
fmt.Println(person1.name)

比较

只能使用 == 和 !=,不能使用 > < >= <=

    // 结构体比较
person2 := Person{name: "zhao", sex: 'm', age: }
person3 := Person{name: "zhao", sex: 'm', age: }
person4 := Person{name: "zhao", sex: 'm', age: }
fmt.Println(person2 == person3) // true
fmt.Println(person3 == person4) // false

相同类型的结构体可以进行赋值

相同类型结构体:成员变量的类型、个数、顺序一致

var tmp Person
tmp = person1
fmt.Println(tmp.name)

因此函数体内部可以使用结构体传参,因为实参可以赋值给相同结构体类型的形参,值传递。几乎不用,内存消耗大,效率低。

func test(person Person)  {
println(person.name)
} func main() { var temp Person
test(temp) }

结构体指针

结构体指针变量定义和初始化

1.顺序初始化和部分初始化

    var man *Person  = &Person{"zhao", 'm', }
fmt.Println(man.name)
var man1 *Person = &Person{name: "zhao", sex: 'm'}
fmt.Println(man1.name)

2.使用new

var  man2 *Person = new(Person);
man2.name = "zhao"
man2.sex =
man2.age =

使用.指针索引成员变量

结构体变量的地址就是结构体首个元素的地址

    fmt.Printf("&tmp = %p \n", &tmp)
fmt.Printf("&tmp.name = %p \n", &tmp.name)

结果

&tmp = 0xc000004500
&tmp.name = 0xc000004500

结构体指针的值就是结构体首个元素的地址

fmt.Printf("man2 = %p\n", man2)
fmt.Printf("&man2.name = %p\n", &man2.name)

结果

man2 = 0xc00008e080
&man2.name = 0xc00008e080

结构体指针作为函数参数

import "fmt"

type Person struct {
name string
sex byte
age int
} func test1(person * Person) {
person.name = "wang"
} func main() { fmt.Println("man2:", man2)
test1(man2)
fmt.Println("man2", man2) }

结果

man2: &{zhao  }
man2 &{wang }

发现通过指针变量可以修改结构体,传引用,使用频率高

也是实参拷贝值给形参,不过这次拷贝的是地址值

fmt.Println(person1.name)
test1(&person1)
fmt.Println(person1.name)

结果

li
wang

函数是一等公民

与其他主要编程语言的差异

1.可以有多个返回值

2.所有参数都是值传递

slice、map、channel会有传引用是错觉,如切片背后是数组,是一个数据结构,里面包含了指向对应数组的指针,数据结构被复制,指针操作的仍是同一块空间,感觉像是传引用

3.函数可以作为变量的值

4.函数可以作为参数和返回值

package fun_test

import (
"fmt"
"math/rand"
"testing"
"time"
) // 多个返回值
func returnMultiValues()(int, int) {
return rand.Intn(), rand.Intn()
} // 函数可以作为参数和返回值
// 计算inner函数运行的时间
func timeSpent(inner func(op int)int) func(opt int) int {
return func(n int) int {
start := time.Now()
ret := inner(n)
fmt.Println("time spent:", time.Since(start).Seconds())
return ret
}
} func slowFun(op int)int{
time.Sleep(time.Second*)
return op
} func TestFn(t *testing.T){
a, _ := returnMultiValues()
t.Log(a)
tsSF := timeSpent(slowFun)
t.Log(tsSF())
}

结果:

=== RUN TestFn
time spent: 1.0000582
--- PASS: TestFn (1.00s)
func_test.go:32: 1
func_test.go:34: 10
PASS

可变参数及defer

可变参数会被转换为数组,通过数组变量来完成

func sum(ops ...int) int  {
s :=
for _, op := range ops{
s += op
}
return s
} func TestParam(t *testing.T) {
s := sum(, , , , )
fmt.Println(s)
}

=== RUN TestParam
15
--- PASS: TestParam (0.00s)
PASS

defer

func clear()  {
fmt.Println("clear resources")
} func TestDefer(t *testing.T) {
defer clear()
fmt.Println("Start")
panic("Fatal error") //defer仍会执行
println("Stop")
}

=== RUN TestDefer
Start
clear resources
--- FAIL: TestDefer (0.00s)
panic: Fatal error [recovered]
panic: Fatal error

会发现出现了异常,clear()依然会执行,

异常之前的fmt.Println("Start")被执行

异常之后的fmt.Println("Stop")没有被执行

Go(二)函数的更多相关文章

  1. Python进阶(二)----函数参数,作用域

    Python进阶(二)----函数参数,作用域 一丶形参角度:*args,动态位置传参,**kwargs,动态关键字传参 *args: ​ 动态位置参数. 在函数定义时, * 将实参角度的位置参数聚合 ...

  2. 深入理解PHP内核(十二)函数-函数的定义、传参及返回值

    原文链接:http://www.orlion.ga/344/ 一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) {    echo $var; ...

  3. Python学习笔记总结(二)函数和模块

    一.函数 函数的作用:可以计算出一个返回值,最大化代码重用,最小化代码冗余,流程的分解. 1.函数相关的语句和表达式 语句        例子 Calls        myfunc(‘diege', ...

  4. C++实验二——函数重载、函数模板、简单类的定义和实现

    一.实验过程 函数重载编程练习 实验要求:编写重载函数add(),实现对int型,double型,complex型数据的加法.在main函数中定义不同类型的数据,调用测试. 代码实现: 先是简单的体验 ...

  5. Mysql(二)函数与连接

    一.函数 1.if函数 if(exp1, exp2, exp3)     判断exp1是否为true(不为0,并且不为nlll),如果为true,返回 exp2的值,否则返回exp3的值. selec ...

  6. python 二——函数、装饰器、生成器、面向对象编程(初级)

    本节内容 1.函数 2.装饰器 3.生成器 4.类 一.函数 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 函数式 ...

  7. iOS学习笔记42-Swift(二)函数和闭包

    上一节我们讲了Swift的基础部分,例如数据类型.运算符和控制流等,现在我们来看下Swift的函数和闭包 一.Swift函数 函数是一个完成独立任务的代码块,Swift中的函数不仅可以像C语言中的函数 ...

  8. 【C++】模板简述(二):函数模板

    我们上文讲了,模板的引入,我们发现在某种特殊的情况下,必须得通过模板才能完美的解决问题. 本文就来简述一下函数模板的基本使用. 一.函数模板格式 template<typename Param1 ...

  9. 《前端之路》- TypeScript(二) 函数篇

    目录 一.定义函数方法 二.定义函数传参 三.可选传参 四.默认传参 五.传递剩余参数 六.函数重载 七.箭头函数 八.总结 一.定义函数方法 在 es5 中定时函数的方法有 命名函数和函数表达式(匿 ...

  10. php基础之二 函数

    一.语句:分支语句,循环语句 1.分支语句: 1.1 if $a = 7;if($a == 5){ echo "相等";}else{ echo "不相等";} ...

随机推荐

  1. es6 新语法分享给爱前端的伙伴

    相信es6大家并不陌生,那么我还是简单介绍一下es6,es是15年发布的,可以用babel转化成es5可以支持低端浏览器,es6是一种新的语法,流行的库基本都是基于es6开发的.所以小伙伴要掌握哦!而 ...

  2. php 系统函数

    realpath();//测试和文档解释不同,可以判断文件是否存在,存在返回路径否则返回false rtrim("Hello World",’d‘);//可以删除指定字符串

  3. [转]解决win10下localhost打不开的问题

    博主刚开始玩Tornado,结果localhost都打不开,各种找寻解决方案,结论都是IIS服务器问题.然而win10下的解决方法居然没人写过...那就我来配图详解下. 打开控制面板--添加或删除程序 ...

  4. Linux任务计划at

    Linux任务计划at 一Linux任务计划介绍 Linux任务计划.周期性任务执行at:未来的某时间点执行一次任务batch:系统自行选择空闲时间去执行此处指定的任务cron:周期性运行某任务 二a ...

  5. NOIP普及组:买铅笔

    参加考试的时候,第一题我足足花了四十多分钟(因为那奇葩的键盘,幸好我向老师报告更换了键盘),还是只得了五十分... 题目描述: P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物.她发现商店一共 ...

  6. 做一个简单的scrapy爬虫

    前言: 做一个简单的scrapy爬虫,带大家认识一下创建scrapy的大致流程.我们就抓取扇贝上的单词书,python的高频词汇. 步骤: 一,新建一个工程scrapy_shanbay 二,在工程中中 ...

  7. Django中执行原生SQL语句【新编辑】

    参考我的个人博客 这部分迁移到了个人博客中:Django中执行原生SQL语句 这里需要补充一下,还有一个extra方法: ret = models.Student.objects.all().extr ...

  8. appium移动端自动化测试的一些感想

    花了一个多月的时间来复习,学习appium+python+android的UI层的自动化测试. 从最开始的环境搭建,都后面运行脚本报错各类错,到优化脚本结构,基本上问题不断. 相比,selenium做 ...

  9. zabbix部署agent

    1.下载zabbix源 rpm -Uvh https://repo.zabbix.com/zabbix/4.2/rhel/7/x86_64/zabbix-release-4.2-2.el7.noarc ...

  10. 同步架构OR异步架构

    把智能系统比喻成KFC营业厅,处理器是窗口和窗口后面的服务员(把一个窗口当作一个核心),指令集是后面排队的人,窗口是数据吞吐量.当中午就餐人多的时候,一个窗口肯定忙不过来,这时候可以增加窗口,有两种方 ...