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. /dev/mem同步写不能使用msync的MS_SYNC选项探究

    问题 做了个测试板子的程序,里面有一项写铁电的功能,要求写入之后立即断电,重启后校验数据准确性:铁电设计是通过内存地址直接映射的,于是,使用mmap直接映射了/dev/mem文件,自然地写入之后使用m ...

  2. 使用INDY解决BASE64回车换行问题

    使用INDY解决BASE64回车换行问题 使用DELPHI EncodeStream(),对流数据进行BASE64编译以后,每隔75个字符,就会添加回车换行符(#$D#$A),这会造成许多问题. 网上 ...

  3. 通过phpMyAdmin优化mysql 数据库可能存在的问题

    通过phpMyAdmin优化mysql 数据库可能存在的问题   文章来源:外星人来地球 欢迎关注,有问题一起学习欢迎留言.评论

  4. Ubuntu16.04 + cuda9.0 +cudnn7.1(转载)

    转载一个详细可用的ubuntu16.04+cuda9.0+cudnn7.1教程. 0 - 参考材料 https://blog.csdn.net/Umi_you/article/details/8026 ...

  5. HTML5Audio/Video全解(疑难杂症)

    1.mp4格式视频无法在chrome中播放 Chrome浏览器支持HTML5,它支持原生播放部分的MP4格式(不用通过Flash等插件).为 什么是部分MP4呢?MP4有非常复杂的含义(见http:/ ...

  6. window.open()详解及浏览器兼容性问题示例探讨

    这篇文章主要介绍了window.open()的使用及浏览器兼容性问题方面的知识,感兴趣的朋友可以参考下   一.基本语法: window.open(pageURL,name,parameters) 其 ...

  7. osg object AnimationPathCallback

    osg::ref_ptr<osg::Node> OSG_Qt_::operateMatrix() { osg::ref_ptr<osg::Group> group = new ...

  8. 阶段5 3.微服务项目【学成在线】_day18 用户授权_07-动态查询用户权限-权限数据模型

    3 动态查询用户权限 3.1 需求分析 截至目前在测试授权时使用的权限数据是静态数据,正常情况的流程是: 1.管理员给用户分配权限,权限数据写到数据库中. 2.认证服务在进行用户认证时从数据库读取用户 ...

  9. Python与C/C++相互调用(python2 调c++那个试了ok)

    一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库比较简单,不经过 ...

  10. 根据DELTA自动生成SQL语句

    上传客户端的CLIENTDATASET.delta到服务器的clientdataset.data,服务端解析clientdataset的数据生成相应的SQL语句. 相对于直接调用datasetprov ...