Golang基础5-指针、结构体、方法、接口

news2024/12/23 8:20:36

指针

和c/c++类似,但是go语言中指针不能进行偏移和运算,安全指针

&(取地址) *(根据地址取值)

nil(空指针)

make和new之前对比:make用于初始化slice,map,channel这样的引用类型

而new用于类型的内存分配,分配的值为类型0值,返回该类型指针

结构体

值传递

没有继承,但是可以通过组合来支持面向对象特性。

结构体中可以包括结构体,但是不能包括本身

简单demo

package main

import "fmt"

type person struct {
    name string
    city string
    age  int8
}

func main() {
    //创建变量
    var p1 person
    p1.name = "pprof.cn"
    p1.city = "北京"
    p1.age = 18
    fmt.Printf("p1=%v\n", p1)  //p1={pprof.cn 北京 18}
    fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"pprof.cn", city:"北京", age:18}

    var p2 = new(person)
    p2.name = "小明"
    p2.city = "武汉"
    p2.age = 10
    fmt.Printf("p2=%v\n", p2)
    fmt.Printf("p2=%#v\n", p2)

    //匿名结构体
    var user struct {
        Name string
        Age  int
    }
    //user := struct{
    //    Name string
    //    Age  int
    //}
    user.Name = "pprof.cn"
    user.Age = 18
    fmt.Printf("%#v\n", user)
}

注意可见性,如果变量名首字母大写,在其他包可以访问(类似于public),否则只能在相同package中访问。

结构体的嵌套

对于Student中匿名嵌套的话,输出对应值,不需要s.p

package main

import "fmt"

type Person struct {
    name string
    age  int
}

// Student 结构体嵌套和匿名嵌套
type Student struct {
    p      Person
    school string
    score  int
}

func main() {
    s := Student{
        p:      Person{name: "张三", age: 18},
        school: "武汉大学",
        score:  100,
    }

    fmt.Println(s.p.name)
}

方法

    • 绑定对象实例,只能为当前包内命名类型定义方法

方法定义:

   func (recevier type) methodName(参数列表)(返回值列表){}

    参数和返回值可以省略
    • 参数recevier任意命名,若方法未曾使用可省略参数名
    • receive可以是T和*T类型。T不能是接口
    • 不支持方法重载
    • 可以使用value或pointer调用全部方法,编译器自动转换

简单demo

receive的类型T和*T之间对比

package main

import "fmt"

// 结构体
type User struct {
    Name  string
    Email string
}

// 假设T,产生副本不影响原变量
func (u User) Notify() {
    fmt.Printf("&u = %p\n", &u)
    fmt.Println("User 通知消息给", u.Name, " 邮箱为:", u.Email)
    u.Email = "Notify"
}

//如果是*T,传入指针,就会影响u1
//func (u *User) Notify() {
//    fmt.Printf("u = %p\n", u)
//    fmt.Println("User 通知消息给", u.Name, " 邮箱为:", u.Email)
//    u.Email = "Notify"
//}

func main() {
    u1 := User{"user1", "user1.com"}
    fmt.Printf("&u1 = %p\n", &u1)
    u1.Notify()
    //u2 := &u1
    fmt.Println(u1) //不影响u1变量
    fmt.Println("*********")
    u2 := &User{"user2", "user2.com"}
    fmt.Printf("u2 = %p\n", u2)

    u2.Notify()
    fmt.Println(u2)

}

func (u User) Notify() 方法时输出,传递副本因此地址不同,修改u不影响mian函数的对象值

func(u *User)Notify()传递指针,影响对象变量的值。

总结:方法就是与特定类型关联的函数,方便相当于c++当中class中的成员函数。

匿名字段demo

通过组合实现于override继承之后覆盖方法的效果。

// 结构体
type User struct {
    Name  string
    Email string
}

type Manager struct {
    User
    Stage string
}

// User的方法
func (u *User) ToString() string {
    return fmt.Sprintf("%s %s\n", u.Name, u.Email)
}

// Manager的方法
func (m *Manager) ToString() string {
    return fmt.Sprintf("%s %s %s\n", m.Name, m.Email, m.Stage)
}

func main() {
    m := Manager{User: User{"李四", "manage.cn"}, Stage: "经理"}
    fmt.Println(m.ToString())
    fmt.Println(m.User.ToString())
}

接口

参考链接:https://www.cnblogs.com/chenny7/p/4497969.html

go语言接口详解:Go 语言接口的原理 | Go 语言设计与实现

interface抽象类型,是一组method的集合,类似于c++中的纯虚函数,如果一个类/对实现了interface中的所有方法就实现了interface接口。通过interface也就是可以实现多态特性。

简单demo

package main

import "fmt"

type Human struct {
    name  string
    age   int
    phone string
}

type Student struct {
    Human  //匿名字段
    school string
    loan   float32
}

type Employee struct {
    Human   //匿名字段
    company string
    money   float32
}

// Human实现SayHi方法
func (h Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

// Human实现Sing方法
func (h Human) Sing(lyrics string) {
    fmt.Println("La la la la...", lyrics)
}

// Employee重载Human的SayHi方法
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)
}

//func (s Student) SayHi() {
//    fmt.Printf("Hi, I am %s, I study in %s. Loan is %f\n", s.name,
//        s.school, s.loan)
//}
//func (s Student) Sing(lyrics string) {
//    fmt.Println("student Sing")
//}

// Interface Men被Human,Student和Employee实现
// 因为这三个类型都实现了这两个方法
type Men interface {
    SayHi()
    Sing(lyrics string)
}

func main() {
    mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.0}
    paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
    sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
    tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}

    //定义Men类型的变量i
    var i Men

    //i能存储Student
    i = mike
    fmt.Println("This is Mike, a Student:")
    i.SayHi()
    i.Sing("November rain")

    //i也能存储Employee
    i = tom
    fmt.Println("This is tom, an Employee:")
    i.SayHi()
    i.Sing("Born to be wild")

    //定义了slice Men
    fmt.Println("Let's use a slice of Men and see what happens")
    x := make([]Men, 3)
    //这三个都是不同类型的元素,但是他们实现了interface同一个接口
    x[0], x[1], x[2] = paul, sam, mike

    for _, value := range x {
        value.SayHi()
    }
}

通过调用接口相当于实现了多态。

可以继续实现嵌入接口。

空接口demo

空interface(interface{})不包含任何的method

所有的类型都实现了空interface

空接口可以存储任意类型

空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。

    // 定义a为空接口,作为函数参数,或者与slice,map等增强灵活性
    var a interface{}
    var i int = 5
    s := "Hello world"
    // a可以存储任意类型的数值
    a = i
    a = s

interface{}可断言类型

空接口断言demo

package main

import "fmt"

type Human struct {
    Name string
    Age  int
}

type Student struct {
    Human
    School string
}

// 作为函数形参
func Show(a interface{}) {
    fmt.Printf("type of:%T value:%v\n", a, a)
}

//判断当前类型
func JustifyType(i interface{}) {
    switch v := i.(type) {
    case string:
        fmt.Println("当前传入为string:", v)
    case int:
        fmt.Println("当前传入为int:", v)
    case Student:
        fmt.Println("当前为Student类型", v)
    default:
        fmt.Println("暂未预料")
    }
}

func main() {
    i := "hello"
    Show(i)
    JustifyType(i)

    j := 10
    Show(j)
    JustifyType(j)

    Show(123)
    JustifyType(123)

    h := Human{"Human", 123}
    Show(h)
    JustifyType(h)

    k := Student{}
    Show(k)
    JustifyType(k)

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1621815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Netty学习——实战篇5 Netty 心跳监测/WebSocket长连接编程 备份

1 心跳监测 MyServer.java public class MyServer {public static void main(String[] args) {NioEventLoopGroup bossGroup new NioEventLoopGroup(1);NioEventLoopGroup workerGroup new NioEventLoopGroup();try {ServerBootstrap serverBootstrap new ServerBootstrap…

CPDA|0到1突破:构建高效数据分析体系的秘密武器

在现今信息爆炸的时代,数据已经渗透到了我们生活的方方面面,成为了决策、创新和竞争优势的关键。因此,构建一套高效的数据分析体系,对于企业和个人而言,都是至关重要的。那么,如何在众多的数据海洋中脱颖而…

一文读懂Partisia Blockhain:兼顾去中心化、安全性与可扩展性

“Partisia Blockhain 解决了区块链领域长期存在的问题,其兼顾了去中心化、安全性以及可扩展性” Partisia Blockchain 是一个具有独特零知识证明预言机以及分片解决方案的 Layer1,解决了困扰整个区块链行业的问题。 目前,多样化的区块链层出…

软考-论文写作-论软件设计模式

题目 素材 框架 一、 摘要 2020年12月,我参加了某省政协委员履职系统的开发。该系统为政协机关人员管理委员信息以及委员完成各项履职提供了全方位的软件支撑。我在该项目重担任系统架构师一职,负责履职系统的架构设计。本文结合作者的实践,以委员履职系统为例,主要讨论软…

计算机网络-IS-IS基础配置实验

前面我们了解了IS-IS的一些基础理论,从建立邻接、链路状态数据库同步以及路由计算,现在开始学习下配置操作。 一、IS-IS配置 网络拓扑图: 拓扑图 IS-IS有Level级别的区分,Level-1可以是性能较低的设备只维护区域内的LSDB&#xff…

035——从GUI->Client->Server->driver实现SPI控制DAC芯片

目录 1、修改GUI 2、修改client 3、server编写 4、driver_handle 5、test 6、 项目管理 1、修改GUI 我想让DAC控制是个滑动条 import PySimpleGUI as sgdef slider_callback(slider_value):print(fCurrent value: {slider_value})layout [[sg.Text(Select a value:)],…

百篇博客 · 千里之行

时光荏苒流逝,白驹匆匆过隙,不知不觉间,Damon小智已经在CSDN上记录了第一百多篇文章。恰逢128天创作纪念日的此刻,我感慨良多,这百余篇博客不仅是我的创作历程,更见证了我在这五年技术生涯中走过心路历程。…

imx6ull -- SPI

SPI 是 Motorola 公司推出的一种同步串行接口 技术,是一种高速、全双工的同步通信总线, SPI 时钟频率相比 I2C 要高很多,最高可以工作 在上百 MHz。 SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般 SP…

【网页在线小游戏源码】

网页在线小游戏源码 效果图部分源码领取源码下期更新预报 效果图 部分源码 index.html <!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <meta id"viewport" na…

Hive——DML(Data Manipulation Language)数据操作语句用法详解

DML 1.Load Load语句可将文件导入到Hive表中。 hive> LOAD DATA [LOCAL] INPATH filepath [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1val1, partcol2val2 ...)];关键字说明&#xff1a; local&#xff1a;表示从本地加载数据到Hive表&#xff1b;否则从HD…

SpringBoot学习之Redis下载安装启动【Windows版本】(三十六)

一、下载Redis for Windows Redis 官方网站没有提供 Windows 版的安装包,但可以通过 GitHub 来下载安装包,下载地址:https://github.com/tporadowski/redis/releases 1、网站提供了安装包和免安装版本,这里我们直接选择下面的免安装版本 2、下载后的压缩包解压以后,如下…

快速新建springboot项目

一、初始化 1.打开IDEA&#xff0c;在Spring initializer这里按照下图项目进行配置。注意&#xff1a;如果jdk是1.8建议将Server URL这里替换为图中的阿里云服务器&#xff0c;否则容易找不到对应的java8&#xff0c;然后点击next 2.在这里提前配置一些需要使用的依赖&#xf…

Node.js和cnpm环境搭建

Node.js和cnpm环境搭建 一、nodejs安装 1.1 傻瓜式一直下一步即可&#xff0c;不需要额外进行任何配置 nodejs下载链接&#xff0c;提取码&#xff1a;5555 1.2 查看是否安装成功 cmd进入命令行界面 输入node -v 显示node版本&#xff0c;显示则安装成功 1.3 改变全局模块路…

npm常用的命令大全(2024-04-21)

nodejs中npm常见的命令 npm主要是node包管理和发布的工具。 npm官网网址&#xff1a;npm | Homehttps://www.npmjs.com/官网英文文档&#xff1a; npm DocsDocumentation for the npm registry, website, and command-line interfacehttps://docs.npmjs.com/about-npm官网中文文…

golang学习笔记(defer基础知识)

什么是defer defer语句用于golang程序中延迟函数的调用&#xff0c; 每次defer都会把一个函数压入栈中&#xff0c; 函数返回前再把延迟的函数取出并执行。 为了方便描述&#xff0c; 我们把创建defer的函数称为主函数&#xff0c; defer语句后面的函数称为延迟函数。延迟函数…

MCU功耗测量

功耗测量 一、相关概念二、功耗的需求三、测量仪器仪表测量连接SMU功能SMU性能指标 四、功耗测量注意点板子部分存在功耗MCU方面&#xff0c;可能存在干扰项仪器仪表方面 一、相关概念 静态功耗和动态功耗&#xff1a;动态功耗为运行功耗&#xff0c;功耗测量注重每MHz下的功耗…

AppleWatch是真的能够减少我iPhone的使用时长

我应该是比较专情的果粉了&#xff0c;我有一台MacBook Pro、iPad Pro、airpods pro 2和iPhone 15 Pro Max。但我还从来没有用过苹果手表。 然后&#xff0c;我就去买了AppleWatchSeries9蜂窝款&#xff0c;并试用了一周&#xff0c;我想知道它是否能帮助我减少使用iPhone的时间…

穿越代码迷雾:解密Tracing技术的神奇力量

穿越代码迷雾&#xff1a;解密Tracing技术的神奇力量 在软件开发和性能优化领域&#xff0c;追踪&#xff08;Tracing&#xff09;技术是一种重要的工具&#xff0c;用于收集和分析程序的执行过程和性能数据。本文将深入讲解Tracing的原理、工作方式以及在不同领域的应用场景&a…

STM32F103ZET6_ADC

ADC主要特征 ● 12位分辨率 ●18个通道 &#xff0c;16个外部通道 2个内部通道 ● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断 ● 单次和连续转换模式 ● 从通道0到通道n的自动扫描模式 ● 自校准 ● 带内嵌数据一致性的数据对齐 ● 采样间隔可以按通道分…