Go语言中同时有函数和方法!

函数: go程序必须要包含一个main函数。main函数不能有任何参数和返回值!

1. 定义方法示例:

func max(num1, num2 int) int {    // 形参类型相同时,可以只写一个类型
// 后面的int代表返回值类型
/* 定义局部变量 */
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
------------------------------------------
func sssss(x int, y string) (string, int) {
return y, x
}
------------------------------------------
func SumAndProduct(A, B int) (Add int, Multiplied int) {
Add = A+B
Multiplied = A*B
return
}
--------------------------------------------------------------
×××××× import(
"fmt"
"math"
)
/* 声明函数变量 */
getSquareRoot := func(x float64) float64 {return math.Sqrt(x)}
/* 使用函数 */
fmt.Println(getSquareRoot(9))

  

2. 当函数有多个返回值时,也可以使用空白标识符 _ 来丢弃某个/些值。

3. 可变参——接受变参的函数是有着形参数量不确定的函数。。。

定义方法:

    func func_name(arg ...int) {} // 这里arg ...int标志此函数可以接收不定数量的int类型的实参

                  // 在函数体中,arg是一个int类型的切片(arg也可以换成args)

4. 参数传递——值传递和引用传递

值传递——就是普通的值传递啊。。

引用传递——使用指针——实质也是值传递。。。

var x int = 2 则若实参为地址 &x, 则形参为 *int 型。 传内存地址比较轻量级(8bytes),我们可以用指针传递体积大的结构体。 如果用参数值传递的话, 在每次copy上面就会花费相对较多的系统开销(内存和时间)。 所以当你要传递大的结构体的时候,用指针是一个明智的选择。

5 闭包: Go语言支持匿名函数,闭包的表现形式一般是匿名函数,通过函数返回一个函数。 闭包会使函数中的变量都被保存在内存中!消耗内存。

×××只要闭包还在使用,那么被闭包引用的变量就会一直存在!!!

func getSequence() func() int {
i := 0
return func() int {
i += 1
return i
}
} func main() {
/* nextNumber 为一个函数 */
// var nextNumber = getSequence() 或者
    nextNumber := getSequence() /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
fmt.Println(nextNumber())
fmt.Println(nextNumber())
fmt.Println(nextNumber())

/* 创建新的函数 nextNumber1,并查看结果 */
nextNumber1 := getSequence()
fmt.Println(nextNumber1())
fmt.Println(nextNumber1())
}

打印结果:
1
2
3
1
2

  

6. 可以声明一个函数类型;然后函数就可以作为值传递了! type testInt func(int) bool   // 声明了一个函数类型testInt, 接收一个int型参数,返回值为bool类型

7. panic和recover: Go语言没有像Java那样的异常机制,不能抛出异常,而是使用panic和recover机制。 panic(...)——当函数F调用panic,函数F的执行被中断,但是F中的延迟函数会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。

recover()让进入恐慌的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。


方法:

1. 定义方法: func (t Type) method(parameter list) { //其中t是一个接收器,可以接收结构体或者非结构体类型 ... }

示例代码:
package main
import "fmt" ​
type Employee struct {
name string
salary int
currency string
}

/*
  displaySalary()的方法接收器为Employee结构体类型
*/
func (e Employee) displaySalary() {
fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {
emp1 := Employee {
name: "Sam Adolf",
salary: 5000,
currency: "$",
}
emp1.displaySalary() // 调用displaySalary() 方法
}

可以定义相同的方法名:相同名称的方法可以在不同的类型上定义,而具有相同名称的函数是不允许的!

package main
import (
"fmt"
"math"
)
type Rectangle struct {
width, height float64
}
type Circle struct {
radius float64
}
// 该 method 属于 Rectangle 类型对象中的方法
func (r Rectangle) area() float64 {
return r.width * r.height
}
// 该 method 属于 Circle 类型对象中的方法
func (c Circle) area() float64 {
return c.radius * c.radius * math.Pi
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
c1 := Circle{10}
c2 := Circle{25}
fmt.Println("Area of r1 is: ", r1.area())
fmt.Println("Area of r2 is: ", r2.area())
fmt.Println("Area of c1 is: ", c1.area())
fmt.Println("Area of c2 is: ", c2.area())
}

  

2. 变量作用域:
       函数内定义的变量称为局部变量,它们的作用域只在函数体内(参数和返回值变量也是局部变量)
       函数外定义的变量称为全局变量,首字母大写全局变量可以在整个包甚至外部包(被导出后)使用
  ​
3. 用指针可以改变值!!

package main
import (
"fmt"
)

type Rectangle struct {
width, height int
}

func (r *Rectangle) setVal() {
r.height = 20
}

func main() {
p := Rectangle{1, 2}
s := p // 此时只是将p的数据拷贝给s了一份,即二者并不是指向同一数据的关系
// p是p,s是s,改变p不会影响s
p.setVal()
mt.Println(p.height, s.height)
}

4. 继承: 如果匿名字段实现了一个method,那么包含这个匿名字段的struct也能调用该method.

type Human struct {
name string
age int
phone string
}
type Student struct {
Human // 匿名字段
school string
}
type Employee struct {
Human //匿名字段
company string
}

func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark.SayHi()
sam.SayHi()
}

  


5. 重写: (就近原则)

package main

import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human //匿名字段
school string
}
type Employee struct {
Human //匿名字段
company string
}
//Human定义method
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
//Employee的method重写Human的method
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
         e.company, e.phone) // Yes you can split into 2 lines here.
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark.SayHi()
sam.SayHi()
}

结果:
Hi, I am Mark you can call me on 222-222-YYYY
Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX

  

Go语言学习笔记(7)——函数和方法的更多相关文章

  1. Go语言学习笔记(五) [函数]

    日期:2014年7月29日   1.函数定义:func (p type) funcname(q int) (r,s int) {return 0,0 }     func: 保留字,用于定义一个函数 ...

  2. 【Go语言学习笔记】函数做参数和闭包

    函数做参数 在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型.类似于重写(同名覆盖). 回调函数:函数有一个参数是函数类型,这个 ...

  3. C语言学习笔记--字符串函数

    字符串函数 需要包含头文件#include<stdio.h> strlen strcmp strcpy strchr strstr strcasestr

  4. python学习笔记之函数(方法)(四)

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在C中叫function,在Java里面叫做method. 定义: ...

  5. C语言学习笔记之函数指针与函数指针数组

    指针函数:本质是一个函数: 是一个返回指针类型的函数int * sum(){ } 函数指针:本质是一个指针: 是一个指向函数的指针 int (*p)(int,int) = sum; p(5,6); i ...

  6. scala学习笔记:函数与方法

    http://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala A Functio ...

  7. Go语言学习笔记七: 函数

    Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...

  8. 大一C语言学习笔记(5)---函数篇-定义函数需要了解注意的地方;定义函数的易错点;详细说明函数的每个组合部分的功能及注意事项

    博主学习C语言是通过B站上的<郝斌C语言自学教程>,对于C语言初学者来说,我认为郝斌真的是在全网C语言学习课程中讲的最全面,到位的一个,这个不是真不是博主我吹他哈,大家可以去B站去看看,C ...

  9. 2017-04-21周C语言学习笔记

    C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...

随机推荐

  1. Js 之常见手势操作插件 Hammer.js

    一.下载 链接:https://pan.baidu.com/s/1UbEtSbT1xcmdzzTCaWmW1A提取码:ldqy 二.案例 三.代码 <!DOCTYPE html> < ...

  2. 搞定TADA68机械键盘的固件修改

    一.先到http://config.qmk.fm,在键盘型号中选择tada68,千万不要选择错了,可在kdemap name中为自己的键位名个名,例如:vimgood 二.修改自己的键位,都是可视化的 ...

  3. Seata 中类SPI使用机制分析

    Seata中采用了与sofa-rpc和dubbo中相同的服务扩展机制.都是基于JAVA自身的服务发现机制-SPI进行再次封装注解,sofa-rpc和dubbo(@Deprecated)中的注解名字叫做 ...

  4. Metaspace 之二--PermGen vs. Metaspace 运行时比较

    PermGen vs. Metaspace 运行时比较 为了更好地理解Metaspace内存空间的运行时行为, 将进行以下几种场景的测试: 使用JDK1.7运行Java程序,监控并耗尽默认设定的85M ...

  5. Facebook开源时间序列内存数据库Beringei,追求极致压缩率——如果是int根据大多数时间序列中的值与相邻数据点相比并没有显著的变化,只要使用XOR将当前值与先前值进行比较,然后存储发生变化的比特。最终,该算法将整个数据集至少压缩了90%

    转自:http://www.infoq.com/cn/news/2017/02/Facebook-Beringei 2017年2月3日,Facebook宣布将开源他们的高性能时序数据存储引擎Berin ...

  6. OpenResty之replace-filter-nginx-module

    原文: openresty/replace-filter-nginx-module 1. 概要 location /t { default_type text/html; echo abc; repl ...

  7. android studio: 让项目通过阿里云 maven jcenter 下载依赖资源

    打开项目根目录下的 build.gradle(Project:项目名称一级的gradle),如下所示添加阿里 maven 库地址: // Top-level build file where you ...

  8. osg Shader 着色器

    #ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osg/Group> #include <os ...

  9. Qt 自定义信号SIGNAL

    emit toLine(lineQStr);connect(vcthread, SIGNAL(toLine(QString)), this, SLOT(appendText(QString)));

  10. springboot集成调用Azkaban

    springboot集成调用Azkaban 一. 说明 1.Azkaban是由Linkedin公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺序运行一组工作和流程,它的配置是通 ...