浅谈Golang 嵌套 interface 的赋值问题

大家还是直接看代码吧~

package main
import (
    "fmt"
) 

func main() {
    s := map[string]interface{}{
        "code":0,
        "msg":"",
        "data":map[string]interface{}{
            "src":"",
        },
    }

    s["data"].(map[string]interface{})["src"] = "abc"           // 修改一个属性,类型转换为map[string]interface{}
    s["data"].(map[string]interface{})["new"] = "bbb"           // 新增一个属性
    fmt.Println(s)
}

补充:Golang interface赋值与取值的实例

大家还是直接看代码吧~

bs := make(map[string]string)
bs["name"] = "张三"
bs["age"]  = "12"
var student interface{}
student = bs
a := student.(map[string]string)   //将interface转换为map类型,如果不确定数据类型的时候可以使用类型断言,确定其类型之后再转换为相对应的类型,然后取值
fmt.Printf("学生的姓名是: \n %v", a["name"])   //结果: 张三
fmt.Printf("学生的数据是: \n %v", student)

补充:go语言学习-接口赋值的两种类型

接口赋值在go语言中分为下面两种情况:

1、将对象实例赋值给接口

在我看来go语言的接口就是c++中虚函数的声明,使用者可以根据自身使用的需要声明一个函数的集合,将需要的方法都在接口中声明,有点像c++中,子类继承父类之后,通过子类对象给父类赋值,因为父类有的方法(除私有方法)子类肯定都有,尤其是虚函数,这样比C++好的地方是go语言中不需要通过继承的方式来实现多态,不同的对象只需要将接口中的所有方法都实现即可,本质上和c++一样,实现这些接口的对象相当于子类,这个接口相当于父类,不同的地方go语言中少了继承的过程,耦合度更低。

将一个接口赋值给另一个接口(同理)

2、将对象实例赋值给接口

这要求该对象实例实现了所有该接口提供的方法,下面是代码实例:

package main
import (
 "fmt"
)
type Integer int
func (a Integer)Less(b Integer) bool{
 return a<b
}
func (a *Integer)Add(b Integer) {
 *a += b
}
type Lesser interface {
 Less(b Integer) bool
}
type LessAdder interface {
 Less(b Integer) bool
 Add(b Integer)
}
func main(){
 fmt.Println("start ...")
 var inter Integer = 1
 var lesser Lesser = inter
 isLess := lesser.Less(3)
 fmt.Println(lesser,"less 3 is ",isLess)
 var lessAdder LessAdder = &inter
 lessAdder.Add(3)
 fmt.Println("lessAdder add 3 is ",inter)
 //fmt.Println("lessAdder is ",*lessAdder) //该条语句不能通过编译
}

第二种方法通过一个接口给另一个接口赋值,在go语言中只要两个接口拥有同样的方法列表(次序不同不要紧),那么他们就是等同的,可以相互赋值

package one
type ReadWriter interface{
 Read(buf []byte)(n int,err error)
 Write(buf []byte)(n int,err error)
}
package two
type Istream interface{
 Read(buf []byte)(n int,err error)
 Write(buf []byte)(n int,err error)
}
var file1 one.ReadWriter = new(file)
var file2 two.Istream = file1
var file3 one.ReadWriter = file2

在go语言中,这两个接口是等价的,因为:

1、任何实现了one.ReadWriter接口的类,均实现了two.ReadWriter

2、任何one.ReadWriter的接口可以赋值给two.ReadWriter,反之亦然

3、在任何地方使用two.ReadWriter的接口和使用one.ReadWriter的接口没有差别

接口赋值并不是要求两个接口是等价的,如果A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A,但是反过来就不成立

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • golang中的空接口使用详解

    1.空接口 Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口.空接口表示,没有任何约束,因此任何类型变量都可以实现空接口.空接口在实际项目中用的是非常多的,用空接口可以表示任意数据类型 func main() { // 定义一个空接口 x, x 变量可以接收任意的数据类型 var x interface{} s := "你好 golang" x = s fmt.Printf("type:%T value:%v\n", x, x) i :=

  • golang 接口嵌套实现复用的操作

    大家还是直接看代码吧~ package main import ( "fmt" ) func main() { start(NewB(C{})) start(NewB(D{})) } type A interface { what() } type B struct { A } type C struct { } func (b C) what() { fmt.Println("this is type C") } type D struct { } func (b

  • 如何判断Golang接口是否实现的操作

    前言 在看一个底层库的的时候,看到了一个比较奇怪的写法,于是乎有了本文. 主要探讨两个问题: 1.利用编译来判断Golang接口是否实现 2.延伸出的make和new的区别 正文 1.利用编译来判断Golang接口是否实现 看了一个底层通用链接池的库,有这么一行代码: var _ Pooler = new(WeightedRoundRobin) 需要解释的是:Pooler是一个接口类型. type Pooler interface { // ... } 刚开始看是疑惑的,为什么new了之后是要抛

  • Golang 使用接口实现泛型的方法示例

    在C/C++中我们可以使用泛型的方法使代码得以重复使用,最常见例如stl functions:vector<int> vint or vector<float> vfloat等.这篇文章将使用interface{...}接口使Golang实现泛型. interface{...}是实现泛型的基础.如一个数组元素类型是interface{...}的话,那么实现了该接口的实体都可以被放置入数组中.注意其中并不一定必须是空接口(简单类型我们可以通过把他转化为自定义类型后实现接口).为什么i

  • golang基础之Interface接口的使用

    接口是一个或多个方法签名名的集合,定义方式如下 type Interface_Name interface { method_a() string method_b() int .... } 只要某个类型拥有该接口的所有方法签名,就算实现该接口,无需显示声明实现了那个接口,这称为structural Typing package main import "fmt" type USB interface { //定义一个接口:方法的集合 Name() string //Name方法,返回

  • golang分层测试之http接口测试入门教程

    前言 前几话主要讲解关于使用golang进行单元测试,在单元测试的上一层就是接口测试,本节主要讲使用golang进行接口测试,其中主要以http协议的接口测试来讲解 golang中的http请求 golang中拥有一个原生的http依赖库:net/http,http服务器的建立还是http客户端的开发,都会使用到这个依赖库,这里主要讲解时client部分,作为请求发起方应用于日常的接口测试,例示代码如下: get请求 package main import ( "fmt" "

  • golang接口IP限流,IP黑名单,IP白名单的实例

    增加中间件 可以选择普通模式和LUA脚本模式,建议选择普通模式,实际上不需要控制的那么精确. package Middlewares import ( "github.com/gin-gonic/gin" "strconv" "time" "voteapi/pkg/app/response" "voteapi/pkg/gredis" "voteapi/pkg/util" ) const

  • 浅谈Golang 嵌套 interface 的赋值问题

    大家还是直接看代码吧~ package main import ( "fmt" ) func main() { s := map[string]interface{}{ "code":0, "msg":"", "data":map[string]interface{}{ "src":"", }, } s["data"].(map[string]in

  • 浅谈Golang是如何读取文件内容的(7种)

    本文旨在快速介绍Go标准库中读取文件的许多选项. 在Go中(就此而言,大多数底层语言和某些动态语言(如Node))返回字节流. 不将所有内容自动转换为字符串的好处是,其中之一是避免昂贵的字符串分配,这会增加GC压力. 为了使本文更加简单,我将使用string(arrayOfBytes)将bytes数组转换为字符串. 但是,在发布生产代码时,不应将其作为一般建议. 1.读取整个文件到内存中 首先,标准库提供了多种功能和实用程序来读取文件数据.我们将从os软件包中提供的基本情况开始.这意味着两个先决

  • 浅谈golang 的高效编码细节

    目录 struct 和 map 用谁呢? 字符串如何拼接是好? 用 + 的方式 使用 fmt.Sprintf() 的方式 使用 strings.Join 的方式 使用 buffer 的方式 xdm,我们都知道 golang 是天生的高并发,高效的编译型语言 可我们也都可知道,工具再好,用法不对,全都白费,我们来举 2 个常用路径来感受一下 struct 和 map 用谁呢? 计算量很小的时候,可能看不出使用 临时 struct 和 map 的耗时差距,但是数量起来了,差距就明显了,且会随着数量越

  • 浅谈Golang的new与make区别是什么

    目录 new make 小结: 区别:在go语言中,make和new都是内存的分配(堆上),但是make只用于slice.map以及channel的初始化(非零值):而new用于类型的内存分配,并且内存置为零.make返回的是引用类型本身:而new返回的是指向类型的指针. 本文操作环境:windows10系统.GO 1.11.2.thinkpad t480电脑. Go语言中new和make都是用来内存分配的原语(allocation primitives).简单的说,new只分配内存,make用

  • 浅谈Golang内存逃逸

    目录 1.什么是内存逃逸 2.什么是逃逸分析 3.小结 4.逃逸分析案例 1.函数返回局部指针变量 2.interface类型逃逸 1.interface产生逃逸 2.指向栈对象的指针不能在堆中 3.闭包产生逃逸 4. 变量大小不确定及栈空间不足引发逃逸 5.总结 1.什么是内存逃逸 在一段程序中,每一个函数都会有自己的内存区域分配自己的局部变量,返回值,这些内存会由编译器在栈中进行分配,每一个函数会分配一个栈帧,在函数运行结束后销毁,但是有些变量我们想在函数运行结束后仍然使用,就需要把这个变量

  • 浅谈golang的json.Unmarshal的坑

    最近在golang业务开发时,遇到一个坑. 我们有个服务,会接收通用的interface对象,然后去给用户发消息.因此会涉及到把各个业务方传递过来的字符串,转成interface对象. 但是因为我的字符串里有一个数字,比如下面demo里的{"number":1234567},而且数字是7位数,在经过json.Unmarshal后,被转成了科学计数法的形式,导致私信发出的链接出现异常,结果报错了. package main import ( "encoding/json&quo

  • 浅谈javascript运算符——条件,逗号,赋值,()和void运算符

    前面的话 javascript中运算符总共有46个,除了前面已经介绍过的算术运算符.关系运算符.位运算符.逻辑运算符之外,还有很多运算符.本文将介绍条件运算符.逗号运算符.赋值运算符.()和void运算符 条件运算符 条件运算符是javascript中唯一的一个三元运算符(三个操作数),有时直接称做'三元运算符'.通常这个运算符写成'?:',当然在代码中往往不会这么简写,因为这个运算符拥有三个操作数,第一个操作数在'?'之前,第二个操作数在'?'和':'之间,第三个操作数在':'之后 varia

  • 浅谈Golang 切片(slice)扩容机制的原理

    我们知道 Golang 切片(slice) 在容量不足的情况下会进行扩容,扩容的原理是怎样的呢?是不是每次扩一倍?下面我们结合源码来告诉你答案. 一.源码 Version : go1.15.6  src/runtime/slice.go //go1.15.6 源码 src/runtime/slice.go func growslice(et *_type, old slice, cap int) slice { //省略部分判断代码 //计算扩容部分 //其中,cap : 所需容量,newcap

  • 浅谈golang fasthttp踩坑经验

    一个简单的系统,结构如下: 我们的服务A接受外部的http请求,然后通过golang的fasthttp将请求转发给服务B,流程非常简单.线上运行一段时间之后,发现服务B完全不再接收任何请求,查看服务A的日志,发现大量的如下错误 从错误原因看是因为连接被占满导致的.进入服务A的容器中(服务A和服务B都是通过docker启动的),通过netstat -anlp查看,发现有大量的tpc连接,处于ESTABLISH.我们采用的是长连接的方式,此时心里非常疑惑:1. fasthttp是能够复用连接的,为什

  • 浅谈Golang Slice切片如何扩容的实现

    目录 一.Slice数据结构是什么? 二.详细代码 1.数据结构 2.扩容原则 3.如何理解扩容规则一 1.当小于1024个元素时 2.当大于1024个元素时 4.如何理解扩容规则二 1.简单理解内存地址更换 总结 一.Slice数据结构是什么? 切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片(slice)是可以看做是一个长度可变的数组.切片(slice)自身并不是动态数组或者数组指

随机推荐