Go-方法-接口-异常处理-错误处理
方法
什么是方法?
方法其实就是一个函数,在 func
这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。
package main import "fmt" type Person struct {
name string
age int
sex int
}
// 语法
//func (a Person) getName {
//
//}
//方法是给对象调用的
//给Person结构体加一个打印名字的方法
func (a Person)printName() {
fmt.Println(a.name)
}
func main() {
p:=Person{name:"GAI"}
p.printName()
} >>>GAI
为什么我们已经有函数了还需要方法呢?
针对指针类型的数据时,方法获取元素比函数更强大。
package main
import "fmt"
//方法 其实就是一个函数
type Person struct {
name string
age int
sex int
}
//语法
//func (a Person) getName() {
//
//}
//方法给对象用
//给Person结构体加一个打印名字的方法
func (a Person)printName() {
fmt.Println(a.name)
}
//func (a Person)changeName(name string) {
// a.name=name
// fmt.Println(a)
//} func (a *Person)changeName(name string) {
a.name=name
fmt.Println(a)
}
//func printName(a Person) {
//// fmt.Println(a.name)
////}
////func printName(a *Person) {
//// fmt.Println(a.name)
////}
func main() {
var p *Person=&Person{name:"lqz"}
//这种也可以,go给你处理了
var p Person=Person{name:"lqz"}
p.changeName("egon")
fmt.Println(p)
p.printName() //为什么我们已经有函数了还需要方法呢
//执行函数
//printName(p)
//printName(&p) }
指针接收器与值接收器
到目前为止,我们只看到了使用值接收器的方法。还可以创建使用指针接收器的方法。值接收器和指针接收器之间的区别在于,
在指针接收器的方法内部的改变对于调用者是可见的,然而值接收器的情况不是这样的。让我们用下面的程序来帮助理解这一点。
//指针接收器与值接收器
//func (值)changeName(name string):在内部修改值,不会影响外部的值
//func (指针)changeName(name string):在内部修改值,会影响外部的值
那么什么时候使用指针接收器,什么时候使用值接收器?
//那么什么时候使用指针接收器,什么时候使用值接收器
//想修改原值,就用指针接收器
//匿名字段的方法
匿名字段的方法
属于结构体的匿名字段的方法可以被直接调用,就好像这些方法是属于定义了匿名字段的结构体一样。
//匿名字段的方法
package main import "fmt" //方法 其实就是一个函数 type Person1 struct {
name string
age int
sex int
Hobby
}
type Hobby struct {
id int
hobbyname string
} func (h Hobby)printHobbyId() {
fmt.Println(h.id)
} func (a Person1)printName() {
fmt.Println(a.name)
}
func (a Person1)printHobbyId() {
fmt.Println("我重写了")
//重用父类的方法
//a.Hobby.printHobbyId()
fmt.Println(a.Hobby.id)
} func main() {
//p:=Person1{name:"lqz",Hobby:Hobby{id:10}}
//
////正常操作
////p.Hobby.printHobbyId()
////非正常操作 方法也提升了
//p.printHobbyId() }
在方法中使用值接收器 与 在函数中使用值参数;在方法中使用指针接收器 与 在函数中使用指针参数
当一个函数有一个值参数,它只能接受一个值参数。
当一个方法有一个值接收器,它可以接受值接收器和指针接收器。
package main import "fmt" //在方法中使用值接收器 与 在函数中使用值参数
//在方法中使用指针接收器 与 在函数中使用指针参数 type Person2 struct {
name string
age int
sex int
}
//方法中使用值接收器
func (a Person2)printName() {
fmt.Println(a.name) }
//方法中使用指针接收器
func (a *Person2)printName2() {
fmt.Println(a.name)
}
//函数中使用值参数
func printName(a Person2) {
fmt.Println(a.name)
}
//在函数中使用指针参数
func printName2(a *Person2) {
fmt.Println(a.name)
} func main() {
//p:=&Person2{name:"lqz"}
//调用值接收器
//p.printName()
//调用指针接收器
//p.printName2()
//调用值函数
//printName(p)
//调用指针函数
//printName2(&p)
//不管是指针接收器还是值接收器,都可以使用值来调用
//不管是指针接收器还是值接收器,都可以使用指针来调用
//函数中,是什么参数,就得传什么参数 }
在非结构体上的方法
package main
import "fmt"
//在非结构体上的方法 //重命名
type MyInt int func (i *MyInt)add() {
(*i)++
fmt.Println(*i)
}
func main() {
var a MyInt=10
a.add()
fmt.Println(a)
}
接口
什么是接口?
在面向对象的领域里,接口一般这样定义:接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。
在 Go 语言中,接口就是方法签名(Method Signature)的集合。当一个类型定义了接口中的所有方法,我们称它实现了该接口。这与面向对象编程(OOP)的说法很类似。接口指定了一个类型应该具有的方法,并由该类型决定如何实现这些方法。
例如,WashingMachine
是一个含有 Cleaning()
和 Drying()
两个方法的接口。任何定义了 Cleaning()
和 Drying()
的类型,都称它实现了 WashingMachine
接口。
类似Python中的接口,定义一个接口,继承可以实现不同的方法,.属性即可调用接口中的属性方法。
package main import "fmt" //接口
//接口是一系列方法的集合
//语法
//type 接口名 interface{
// 方法一
// 方法二
//}
//定义了一个鸭子接口
type Duck interface {
run()
speak()
}
//结构体实现该接口(只要实现了接口中的所有方法,该结构体就叫实现了Duck接口)
//侵入式接口和非侵入式接口(了解)
//定义普通鸭子结构体
type PDuck struct {
name string
age string
} func (p PDuck)run() {
fmt.Println("我是普通鸭子,我名字叫",p.name,"我走路歪歪扭扭")
}
func (p PDuck)speak() {
fmt.Println("我是普通鸭子,我名字叫",p.name,"我嘎嘎说话")
} //定义一个唐老鸭,实现鸭子接口
type TDuck struct {
name string
age string
wife bool
} func (p TDuck)run() {
fmt.Println("我是普通鸭子,我名字叫",p.name,"我走路歪歪扭扭")
}
func (p TDuck)speak() {
fmt.Println("我是普通鸭子,我名字叫",p.name,"我嘎嘎说话")
} func main() {
pD:=PDuck{name:"水鸭子"}
tD:=TDuck{name:"唐老鸭"}
//写一个函数,让鸭子说话,不管是唐老鸭还是普通鸭子
//speak(pD)
//speak(tD)
//var d Duck
//d=pD
//d=tD
//fmt.Println(d)
//问题研究:我想在函数中拿出唐老鸭的wife属性
speak(tD)
speak(pD)
}
//func speak(p PDuck) {
// p.speak()
//}
//func speak2(p TDuck) {
// p.speak()
//}
//func speak(p Duck) {
// p.speak()
//}
//我想在函数中拿出唐老鸭的wife属性
//func speak(p Duck) {
// //类型断言,我断言你是TDuck类型,如果没有问题,转成TDuck类型
// a:=p.(TDuck)
// fmt.Println(a.wife)
// p.speak()
//} func speak(p Duck) {
switch a:=p.(type) {
case PDuck:
//判断好了,你是普通鸭子,把鸭子名字拿出来
fmt.Println("你是普通鸭子")
fmt.Println(a.name)
case TDuck:
//判断好了,你是唐老鸭,把唐老鸭的wife拿出来
fmt.Println("你是唐老鸭") fmt.Println(a.wife) }
}
空接口
没有包含方法的接口称为空接口。空接口表示为 interface{}
。由于空接口没有方法,因此所有类型都实现了空接口。
package main import "fmt" //空接口(一个方法都没有)
//匿名空接口
//所有的数据类型都实现了空接口
type Empty interface { }
type TDuck2 struct {
name string
age string
wife bool
}
func main() {
test(1)
test("ssss")
test(TDuck2{})
test(10.45)
var a Empty =1
var b Empty ="dddd" } //func test(a Empty) {
// fmt.Println(a)
//} func test(a interface{}) {
switch a.(type) {
case int:
fmt.Println("你是int类型")
case string:
fmt.Println("你是string ")
case TDuck2:
fmt.Println("你是唐老鸭")
default:
fmt.Println("我不知道你是什么类型") }
}
函数接收空接口作为参数,因此,可以给这个函数传递任何类型。
类型断言
类型断言用于提取接口的底层值(Underlying Value)。
类型选择(Type Switch)
类型选择用于将接口的具体类型与很多 case 语句所指定的类型进行比较。它与一般的 switch 语句类似。唯一的区别在于类型选择指定的是类型,而一般的 switch 指定的是值。
类型选择的语法类似于类型断言。类型断言的语法是 i.(T)
,而对于类型选择,类型 T
由关键字 type
代替。
接口的其他方法:
实现多个接口
类型可以实现多个接口。我们看看下面程序是如何做到的。
package main import "fmt" //实现多个接口
//type SalaryCalculator interface {
// DisplaySalary()
//}
//
//type LeaveCalculator interface {
// CalculateLeavesLeft() int
//}
//
//type Employee struct {
// firstName string
// lastName string
// basicPay int
// pf int
// totalLeaves int
// leavesTaken int
//}
//
//func (e Employee) DisplaySalary() {
// fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
//}
//
//func (e Employee) CalculateLeavesLeft() int {
// return e.totalLeaves - e.leavesTaken
//}
//
//func main() {
// e := Employee {
// firstName: "Naveen",
// lastName: "Ramanathan",
// basicPay: 5000,
// pf: 200,
// totalLeaves: 30,
// leavesTaken: 5,
// }
// var s SalaryCalculator = e
// s.DisplaySalary()
// var l LeaveCalculator = e
// fmt.Println("\nLeaves left =", l.CalculateLeavesLeft())
//} //接口的零值 nil 接口是引用类型
type Describer interface {
Describe()
} func main() {
var d1 Describer
if d1 == nil {
fmt.Println("xxxx")
}
}
接口的嵌套
尽管 Go 语言没有提供继承机制,但可以通过嵌套其他的接口,创建一个新接口。
//接口嵌套
type SalaryCalculator interface {
DisplaySalary()
} type LeaveCalculator interface {
CalculateLeavesLeft() int
} type EmployeeOperations interface {
SalaryCalculator
LeaveCalculator
} type Employee struct {
firstName string
lastName string
basicPay int
pf int
totalLeaves int
leavesTaken int
} func (e Employee) DisplaySalary() {
fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
} func (e Employee) CalculateLeavesLeft() int {
return e.totalLeaves - e.leavesTaken
} func main() {
e := Employee {
firstName: "Naveen",
lastName: "Ramanathan",
basicPay: 5000,
pf: 200,
totalLeaves: 30,
leavesTaken: 5,
}
var empOp EmployeeOperations = e
empOp.DisplaySalary()
fmt.Println("\nLeaves left =", empOp.CalculateLeavesLeft())
}
接口的零值
接口的零值是 nil
。对于值为 nil
的接口,其底层值(Underlying Value)和具体类型(Concrete Type)都为 nil
。
//接口的零值 nil 接口是引用类型
type Describer interface {
Describe()
} func main() {
var d1 Describer
if d1 == nil {
fmt.Println("xxxx")
}
}
异常处理
错误表示程序中出现了异常情况。比如当我们试图打开一个文件时,文件系统里却并没有这个文件。这就是异常情况,它用一个错误来表示。
在 Go 中,错误一直是很常见的。错误用内建的 error
类型来表示。
就像其他的内建类型(如 int
、float64
等),错误值可以存储在变量里、作为函数的返回值等等。
总结:
//异常处理
//defer panic recover //defer 表示延迟调用,即便程序出现严重错误,也会执行
//panic 就是python中的raise(主动抛出异常)
//recover 恢复程序,继续执行
常见异常处理的方法:
package main import "fmt"
func main() {
//先注册,后调用
//defer fmt.Println("xxxx")
//defer fmt.Println("yyy")
f1()
f2() f3() } func f1() {
fmt.Println("f1...")
} func f2() {
defer func() {
if a:=recover();a!=nil{
//a 如果不等于nil,表示程序出了异常,a 就是异常信息
//a 等于nil,表示没有异常
//fmt.Println("出错了") fmt.Println(a)
}
//用于会被执行(相当于finally)
}()
fmt.Println("f2...")
//var a =make([]int,3,3)
//fmt.Println(a[4])
panic("你给我出去")
}
func f3() { fmt.Println("f3...")
}
错误处理
错误表示程序中出现了异常情况。比如当我们试图打开一个文件时,文件系统里却并没有这个文件。这就是异常情况,它用一个错误来表示。
在 Go 中,错误一直是很常见的。错误用内建的 error
类型来表示。
就像其他的内建类型(如 int
、float64
等),错误值可以存储在变量里、作为函数的返回值等等。
package main import (
"errors"
"fmt"
) //错误 func circleArea(radius int) (int, error) {
if radius < 0 {
return 0, errors.New("错误信息")
//panic("xddd")
}
return 100, nil
} func main() {
a,_:=circleArea(-10)
if err!=nil{
fmt.Println(err)
}
//fmt.Println(err)
fmt.Println(a)
_,err:=fmt.Println()
if err!=nil{
fmt.Println("打印出错")
}
}
主动的返回error
Go-方法-接口-异常处理-错误处理的更多相关文章
- Oracle 11g RAC环境下Private IP修改方法及异常处理
Oracle 11g RAC环境下Private IP修改方法及异常处理 Oracle 11g RAC环境下Private IP修改方法及异常处理 一. 修改方法 1. 确认所有节点CRS服务以启动 ...
- Java异常处理错误
Java异常处理错误 研究发现,在编译阶段的最佳时机错误,序之前.然而,编译期间并不能找出全部的错误,余下的问题必须在执行阶段解决.这就须要错误源通过某种方式把适当的信息传给某个接收者,该接收者知道怎 ...
- go 函数 方法 接口
概论 函数 方法 接口 概论 方法在编译时静态绑定,依托于具体的类型 接口对应的方法是在运行时动态绑定 进程内初始化顺序 初始化导入包的常量和变量(可以导出的变量)--->包的init函数,不同 ...
- 后端API接口的错误信息返回规范
前言 最近我司要制定开发规范.在讨论接口返回的时候,后端的同事询问我们前端,错误信息的返回,前端有什么意见? 所以做了一些调研给到后端的同事做参考. 错误信息返回 在使用API时无可避免地会因为各种情 ...
- python 处理protobuf 接口常见错误
python 处理protobuf 接口常见错误 1.问题 : Assignment not allowed to repeated field '> http://www.coin163.co ...
- 黑盒测试用例设计方法&理论结合实际 -> 错误推断法
一 概念 基于经验和直觉推测程序中所有可能存在的各种错误, 从而有针对性的设计测试用例的方法. 二 错误推断法的应用 基本思想:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试 ...
- 解决和排查 "必须使用适当的属性和方法修改 User-Agent" 错误时遇到的一些坑
解决 必须使用适当的属性和方法修改 User-Agent 错误 问题描述:近在项目中有一个需求为需要在 Http 的Header里面添加一个User-Agent参数,当请求时.项目本身的目标框架是 . ...
- 在执行context.getContentResolver.query()方法时出现错误。
1. 在执行context.getContentResolver.query()方法时出现错误. 07-15 18:46:13.470: E/AndroidRuntime(13624): FATAL ...
- Saiku ui-settings接口404错误避免(二十九)
Saiku ui-settings接口404错误避免 自己手动编译的saiku ,不知道为什么前端总是报错 /saiku/rest/saiku/info/ui-settings 404NotFo ...
随机推荐
- java代码静态分析工具
需求:有些基础类型的遍历,值希望它被赋予指定的几个值,赋予其他值能够别编译器(IDEA/eclipse)提醒 Android studu结合自己的插件,引入 <!-- https://mvnre ...
- BeanUtils使用将一个对象拷贝到另外一个对象
这里的BeanUtils是BeanUtils是org.springframework.beans.BeanUtils,和org.apache.commons.beanutils.BeanUtils是有 ...
- 五十二、SAP中的可编辑表格LVC
一.之前我们写的表格如下,都是通过WRITE输出,不支持同步编辑等操作,给人感觉非常之LOW 二.在SAP中还存在另外一种可编辑的表格,叫LVC表格,效果如下, 三.此可标记表格是座位SAP内置模块来 ...
- 097-PHP循环使用next取数组元素二
<?php function return_item($arr, $num = 0) { //定义函数 if ($num < 0) { end($arr); //将数组指针指向最后一个元素 ...
- php观察者模式。
第一次写博客,大家多多关照!欢迎拍砖哦! 我也刚学设计模式,所以记录下来. <?php class person{ public $name; public $birthday; public ...
- ACM-单词接龙
题目描述:单词接龙 问题描述:单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们己知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙" 中出现 ...
- python爬取网页文本、图片
从网页爬取文本信息: eg:从http://computer.swu.edu.cn/s/computer/kxyj2xsky/中爬取讲座信息(讲座时间和讲座名称) 注:如果要爬取的内容是多页的话,网址 ...
- vue-cli 官方脚手架 eslink配置 恢复serve状态下的打印
使用官方脚手架 打印会提示保存,主要是eslink的配置(在package.json文件夹里面修改) 配置说明 下面是抄的 "eslintConfig": { "root ...
- UVA - 12118 Inspector's Dilemma(检查员的难题)(欧拉回路)
题意:有一个n个点的无向完全图,找一条最短路(起点终点任意),使得该道路经过E条指定的边. 分析: 1.因为要使走过的路最短,所以每个指定的边最好只走一遍,所以是欧拉道路. 2.若当前连通的道路不是欧 ...
- git使用代理
在使用git科隆一个repo的时候,因为这个repo的子模块是托管在google上的,还是因为gfw导致子模块科隆不下来 只好使用代理了,那么怎么配置git使用代理呢 代码如下 因为我用的是ss所以这 ...