《快学 Go 语言》第 8 课 —— 程序大厦是如何构建起来的

第2章:Go工具箱 - 基础语法全接触 Go语言命名与变量声明指南 Go语言的命名规则要求标识符以字母或下划线开头,区分大小写,并包含25个关键字和30多个预定义名字。社区惯例推荐使用驼峰命名法,大写字母开头的名称可被外部包访问。 变量声明支持四种方式: var声明:var 变量名 类型 = 表达式,可省略类型或表达式 包级变量:在main函数执行前初始化 简短声明:使用:=操作符,需至少声明一个新变量 new表达式:创建匿名变量并返回指针 指针用于直接操作内存地址,new(T)创建T类型的零值变量并返回指针。特殊类型如struct{}不占内存空 阅读详情

640?wx_fmt=jpeg

本节我们要开讲 Go 语言在数据结构上最重要的概念 —— 结构体。如果说 Go 语言的基础类型是原子,那么结构体就是分子。分子是原子的组合,让形式有限的基础类型变化出丰富多样的形态结构。结构体里面装的是基础类型、切片、字典、数组以及其它类型的结构体等等。

640?wx_fmt=png

因为结构体的存在,Go 语言的变量才有了更加丰富多彩的形式,Go 语言程序的高楼大厦正是通过结构体一层层组装起来的。

结构体类型的定义

结构体和其它高级语言里的「类」比较类似。下面我们使用结构体语法来定义一个「圆」型

type Circle struct {
  x int
  y int
  Radius int
}

结构体变量的创建

创建一个结构体变量有多种形式,我们先看结构体变量最常见的创建形式

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c Circle = Circle {
        x: 100,
        y: 100,
        Radius: 50,  // 注意这里的逗号不能少
    }
    fmt.Printf("%+v\n", c)
}

----------
{x:100 y:100 Radius:50}

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c1 Circle = Circle {
        Radius: 50,
    }
    var c2 Circle = Circle {}
    fmt.Printf("%+v\n", c1)
    fmt.Printf("%+v\n", c2)
}

----------
{x:0 y:0 Radius:50}
{x:0 y:0 Radius:0}

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c Circle = Circle {100, 100, 50}
    fmt.Printf("%+v\n", c)
}

-------
{x:100 y:100 Radius:50}

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c *Circle = &Circle {100, 100, 50}
    fmt.Printf("%+v\n", c)
}

-----------
&{x:100 y:100 Radius:50}

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c *Circle = new(Circle)
    fmt.Printf("%+v\n", c)
}

----------
&{x:0 y:0 Radius:0}

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c Circle
    fmt.Printf("%+v\n", c)
}

var c1 Circle = Circle{}
var c2 Circle
var c3 *Circle = new(Circle)

零值结构体和 nil 结构体

nil 结构体是指结构体指针变量没有指向一个实际存在的内存。这样的指针变量只会占用 1 个指针的存储空间,也就是一个机器字的内存大小。

var c *Circle = nil

结构体的内存大小

Go 语言的 unsafe 包提供了获取结构体内存占用的函数 Sizeof()

package main

import "fmt"
import "unsafe"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c Circle = Circle {Radius: 50}
    fmt.Println(unsafe.Sizeof(c))
}

-------
24

结构体的拷贝

结构体之间可以相互赋值,它在本质上是一次浅拷贝操作,拷贝了结构体内部的所有字段。结构体指针之间也可以相互赋值,它在本质上也是一次浅拷贝操作,不过它拷贝的仅仅是指针地址值,结构体的内容是共享的。

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func main() {
    var c1 Circle = Circle {Radius: 50}
    var c2 Circle = c1
    fmt.Printf("%+v\n", c1)
    fmt.Printf("%+v\n", c2)
    c1.Radius = 100
    fmt.Printf("%+v\n", c1)
    fmt.Printf("%+v\n", c2)

    var c3 *Circle = &Circle {Radius: 50}
    var c4 *Circle = c3
    fmt.Printf("%+v\n", c3)
    fmt.Printf("%+v\n", c4)
    c3.Radius = 100
    fmt.Printf("%+v\n", c3)
    fmt.Printf("%+v\n", c4)
}

---------------
{x:0 y:0 Radius:50}
{x:0 y:0 Radius:50}
{x:0 y:0 Radius:100}
{x:0 y:0 Radius:50}
&{x:0 y:0 Radius:50}
&{x:0 y:0 Radius:50}
&{x:0 y:0 Radius:50}
&{x:0 y:0 Radius:50}

无处不在的结构体

通过观察 Go 语言的底层源码,可以发现所有的 Go 语言内置的高级数据结构都是由结构体来完成的。

切片头的结构体形式如下,它在 64 位机器上将会占用 24 个字节

type slice struct {
  array unsafe.Pointer  // 底层数组的地址
  len int // 长度
  cap int // 容量
}

type string struct {
  array unsafe.Pointer // 底层数组的地址
  len int
}

type hmap struct {
  count int
  ...
  buckets unsafe.Pointer  // hash桶地址
  ...
}

结构体中的数组和切片

在数组与切片章节,我们自习分析了数组与切片在内存形式上的区别。数组只有「体」,切片除了「体」之外,还有「头」部。切片的头部和内容体是分离的,使用指针关联起来。请读者尝试解释一下下面代码的输出结果

package main

import "fmt"
import "unsafe"

type ArrayStruct struct {
    value [10]int
}

type SliceStruct struct {
    value []int
}

func main() {
    var as = ArrayStruct{[...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
    var ss = SliceStruct{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}
    fmt.Println(unsafe.Sizeof(as), unsafe.Sizeof(ss))
}

-------------
80 24

结构体的参数传递

函数调用时参数传递结构体变量,Go 语言支持值传递,也支持指针传递。值传递涉及到结构体字段的浅拷贝,指针传递会共享结构体内容,只会拷贝指针地址,规则上和赋值是等价的。下面我们使用两种传参方式来编写扩大圆半径的函数。

package main

import "fmt"

type Circle struct {
    x int
    y int
    Radius int
}

func expandByValue(c Circle) {
    c.Radius *= 2
}

func expandByPointer(c *Circle) {
    c.Radius *= 2
}

func main() {
    var c = Circle {Radius: 50}
    expandByValue(c)
    fmt.Println(c)
    expandByPointer(&c)
    fmt.Println(c)
}

---------
{0 0 50}
{0 0 100}

结构体方法

Go 语言不是面向对象的语言,它里面不存在类的概念,结构体正是类的替代品。类可以附加很多成员方法,结构体也可以。

package main

import "fmt"
import "math"

type Circle struct {
 x int
 y int
 Radius int
}

// 面积
func (c Circle) Area() float64 {
 return math.Pi * float64(c.Radius) * float64(c.Radius)
}

// 周长
func (c Circle) Circumference() float64 {
 return 2 * math.Pi * float64(c.Radius)
}

func main() {
 var c = Circle {Radius: 50}
 fmt.Println(c.Area(), c.Circumference())
 // 指针变量调用方法形式上是一样的
 var pc = &c
 fmt.Println(pc.Area(), pc.Circumference())
}

-----------
7853.981633974483 314.1592653589793
7853.981633974483 314.1592653589793

结构体的指针方法

如果使用上面的方法形式给 Circle 增加一个扩大半径的方法,你会发现半径扩大不了。

func (c Circle) expand() {
  c.Radius *= 2
}

func (c *Circle) expand() {
  c.Radius *= 2
}

通过指针访问内部的字段需要 2 次内存读取操作,第一步是取得指针地址,第二部是读取地址的内容,它比值访问要慢。但是在方法调用时,指针传递可以避免结构体的拷贝操作,结构体比较大时,这种性能的差距就会比较明显。

还有一些特殊的结构体它不允许被复制,比如结构体内部包含有锁时,这时就必须使用它的指针形式来定义方法,否则会发生一些莫名其妙的问题。

内嵌结构体

结构体作为一种变量它可以放进另外一个结构体作为一个字段来使用,这种内嵌结构体的形式在 Go 语言里称之为「组合」。下面我们来看看内嵌结构体的基本使用方法

package main

import "fmt"

type Point struct {
    x int
    y int
}

func (p Point) show() {
  fmt.Println(p.x, p.y)
}

type Circle struct {
    loc Point
    Radius int
}

func main() {
    var c = Circle {
        loc: Point {
            x: 100,
            y: 100,
        },
        Radius: 50,
    }
    fmt.Printf("%+v\n", c)
    fmt.Printf("%+v\n", c.loc)
    fmt.Printf("%d %d\n", c.loc.x, c.loc.y)
 c.loc.show()
}

----------------
{loc:{x:100 y:100} Radius:50}
{x:100 y:100}
100 100
100 100

匿名内嵌结构体

还有一种特殊的内嵌结构体形式,内嵌的结构体不提供名称。这时外面的结构体将直接继承内嵌结构体所有的内部字段和方法,就好像把子结构体的一切全部都揉进了父结构体一样。匿名的结构体字段将会自动获得以结构体类型的名字命名的字段名称

package main

import "fmt"

type Point struct {
    x int
    y int
}

func (p Point) show() {
    fmt.Println(p.x, p.y)
}

type Circle struct {
    Point // 匿名内嵌结构体
    Radius int
}

func main() {
    var c = Circle {
        Point: Point {
            x: 100,
            y: 100,
        },
        Radius: 50,
    }
    fmt.Printf("%+v\n", c)
    fmt.Printf("%+v\n", c.Point)
    fmt.Printf("%d %d\n", c.x, c.y) // 继承了字段
    fmt.Printf("%d %d\n", c.Point.x, c.Point.y)
 c.show() // 继承了方法
 c.Point.show()
}

-------
{Point:{x:100 y:100} Radius:50}
{x:100 y:100}
100 100
100 100
100 100
100 100

Go 语言的结构体没有多态性

Go 语言不是面向对象语言在于它的结构体不支持多态,它不能算是一个严格的面向对象语言。多态是指父类定义的方法可以调用子类实现的方法,不同的子类有不同的实现,从而给父类的方法带来了多样的不同行为。下面的例子呈现了 Java 类的多态性。

class Fruit {
  public void eat() {
    System.out.println("eat fruit");
  }

  public void enjoy() {
    System.out.println("smell first");
    eat();
    System.out.println("clean finally");
  }
}

class Apple extends Fruit {
  public void eat() {
    System.out.println("eat apple");
  }
}

class Banana extends Fruit {
  public void eat() {
    System.out.println("eat banana");
  }
}

public class Main {
  public static void main(String[] args) {
    Apple apple = new Apple();
    Banana banana = new Banana();
    apple.enjoy();
    banana.enjoy();
  }
}

----------------
smell first
eat apple
clean finally
smell first
eat banana
clean finally

Go 语言的结构体明确不支持这种形式的多态,外结构体的方法不能覆盖内部结构体的方法。比如我们用 Go 语言来改写上面的水果例子观察一下输出结果。

package main

import "fmt"

type Fruit struct {}

func (f Fruit) eat() {
    fmt.Println("eat fruit")
}

func (f Fruit) enjoy() {
    fmt.Println("smell first")
    f.eat()
    fmt.Println("clean finally")
}

type Apple struct {
    Fruit
}

func (a Apple) eat() {
    fmt.Println("eat apple")
}

type Banana struct {
    Fruit
}

func (b Banana) eat() {
    fmt.Println("eat banana")
}

func main() {
    var apple = Apple {}
    var banana = Banana {}
    apple.enjoy()
    banana.enjoy()
}

----------
smell first
eat fruit
clean finally
smell first
eat fruit
clean finally

面向对象的多态性需要通过 Go 语言的接口特性来模拟,这就是下一节我们要讲的主题。

Go init函数本质:静态初始化钩子与生命周期守门人 init是Go语言中用于包级静态初始化的核心机制,它并非程序入口,而是编译期注入的、仅执行一次的隐式钩子,承担类型注册、全局变量预设等前置准备任务。其执行遵循严格的依赖拓扑排序,确保跨包初始化顺序可预测。技术价值在于提供无状态、幂等、低开销的初始化能力,适用于日志配置、常量映射、驱动注册等场景;但不适用于I/O操作、goroutine启动或依赖动态环境的逻辑。真实生产中,滥用init易引发启动阻塞、资源泄漏与调试困难——因此现代Go工程更倾向显式初始化函数、wire依赖注入或fx生命周期管理器。本文深入解析 阅读详情

相关推荐

告别上位机!用MCGS触摸屏+FTP服务器,5分钟搞定工控机文件自动同步

本文介绍了一种工业自动化领域的高效解决方案,通过MCGS触摸屏结合FTP服务器实现工控机文件的自动同步,无需开发上位机软件。该方案特别适用于图像采集、参数同步、数据备份等场景,具有成本低、可靠性高、维护简便等优势。详细配置指南和实战案例帮助用户快速实现零代码文件同步。

weixin_30872499的博客 561

深入理解Go语言基础之数据类型全解析

有带符号的int8(-128 到 127)、int16(-32768 到 32767)、int32(-2147483648 到 2147483647)、int64,以及无符号的uint8(0 到 255)、uint16(0 到 65535)、uint32(0 到 4294967295)、uint64。此外,还有与系统架构相关的int和uint,在32位系统上等同于int32和uint32,在64位系统上等同于int64和uint64。Go语言的数据类型丰富多样,每种类型都有其独特的用途和特性。

2501_91651758的博客 575

基于STM32的Keil5代码自动补全设置操作指南

掌握Keil5代码自动补全设置技巧,提升STM32开发效率。通过合理配置编辑器选项,实现智能提示与语法补全,让嵌入式编程更流畅,尤其适合使用keil5代码自动补全设置的开发者快速上手。

weixin_32287387的博客 763

Springboot公交大厦停车场管理系统w4lan(程序+源码+数据库+调试部署+开发环境)

随着城市化进程的加快,停车难问题日益凸显,特别是作为城市交通枢纽的公交大厦,其停车场的管理效率直接影响到市民的出行体验。传统的停车场管理方式,如纸质票据、人工收费等,已难以满足现代需求。智能化、自动化的停车场管理系统成为解决之道。本项目旨在开发一套功能全面、性能稳定的公交大厦停车场管理系统,以提升管理效率,优化车位资源配置,并为用户提供便捷、智能的停车服务。

CK3037的博客 1026

Mplus—验证性因素分析(Confirmatory Factor Analysis, CFA)

介绍一阶和二阶验证性因素分析概况及在Mplus中的操作方法。

m0_54401011的博客 1万+

吉林大学软件工程章节测验 第九章 答案+解析

4.【判断题】估算软件规模有代码行技术和功能点技术两种方法,其中代码行方法估计实现一个功能所需要的源程序行数,其不依赖项目所使用的开发语言,并且具有较好的直观性。3.【单选题】软件项目估算时,若计划人员对每个功能分别按最佳的、可能的、悲观的三种情况给出功能点估计值,记作a, m, b,则估算的期望值E的公式为( )。8.【判断题】在工程网络图中,如果在由起始事件至终止事件所构成的一条路径上,所有事件的最早时刻都和最迟时刻都相同,那么这条路径就是关键路径。4.【单选题】配置管理贯穿软件开发的整个过程。

m0_51459931的博客 1433

百万年薪挖了个P8程序员,难道是“水货”?

点击蓝色“程序猿DD”关注我回复“资源”获取独家整理的学习资料!>>阿里云8月最新优惠,点击查看<<大厦新搬进来一家创业公司,老板红光满面地提着果...

程序猿DD 2005

SPI为什么不需要加上拉电阻

大家好,我是记得诚。I2C因为其开漏的结构,无法输出高电平,所以外部加上拉电阻。我们在使用SPI的时候,发现是不需要加上拉电阻的。主要因为SPI多为推挽的结构,推挽电路,高低电平都可以输出,所以外部不需要加上拉电阻。推挽电路可以用2个三极管或者2个MOS管搭建而成。

记得诚 2631

从零构建你的网络安全知识大厦:一份详尽的阶段学习计划与核心技能清单

网络安全产业就像一个江湖,各色人等聚集。相对于欧美国家基础扎实(懂加密、会防护、能挖洞、擅工程)的众多名门正派,我国的人才更多的属于旁门左道(很多白帽子可能会不服气),因此在未来的人才培养和建设上,需要调整结构,鼓励更多的人去做“正向”的、结合“业务”与“数据”、“自动化”的“体系、建设”,才能解人才之渴,真正的为社会全面互联网化提供安全保障。

Misdirection_XG的博客 797

ShowDoc item_id 未授权SQL注入漏洞复现

2024年6月,ShowDoc官方发布新版本修复了一个SQL注入漏洞。鉴于该漏洞无前置条件,易于利用,且默认情况下可暴破用户token获取系统后台权限,建议所有使用该系统的企业尽快升级修复,以确保系统安全。

0xSec 2360

性能测试能力提升-线程、并发、吞吐量、TPS、QPS、响应时间

接着上一篇的知识:性能测试能力提升-关于性能测试,本篇文章,我们将主要介绍以下几方面的知识: 线程数&并发用户数 相对并发&绝对并发 吞吐量 TPS&QPS 响应时间

程序员小杨哥的博客 4589

Go语言手搓SHA-256算法:从原理到实现的完整指南

加密哈希函数是现代计算机安全与数据完整性的基石,它能够将任意长度的输入数据映射为固定长度的输出摘要,具备单向性和抗碰撞性等核心特性。SHA-256作为SHA-2家族的重要成员,其设计基于Merkle-Damgård结构,通过预处理、消息分块和迭代压缩等步骤,确保了输出的唯一性与高度随机性。该算法在密码存储、数字签名、区块链(如比特币)以及文件校验等场景中具有不可替代的技术价值。本文聚焦于Go语言实现,通过详细拆解消息填充、消息调度、压缩函数等核心模块,并融入位操作和流式处理等工程实践,帮助开发者深入理解SH

weixin_34411563的博客 378

Xiaojie雷达之路---手把手教你从串口获取雷达原始数据(一)---新建工程(开始)

Hello,大家好,我是Xiaojie,欢迎大家能够和Xiaojie来一起学习毫米波雷达知识,Xiaojie准备连载一个系列的文章---利用串口获取毫米波雷达中的原始数据,本系列文章将从新建工程到最后原始数据显示到PC上进行逐步介绍,这个系列的文章大约是一个4-5篇左右。本篇文章呢,主要讲的是如何新建一个毫米波雷达的工程。

XiaoJie的博客 5811

软件设计师の第二章:程序设计语言

本专栏系列文章,将专注于分享我本人在备考软件设计师过程中的一些笔记,方法,经验,总结等等,希望能够帮助到您,祝您顺利通过软考!

yang_xs的博客(只讲干货) 474

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

设计模式:程序员跳不开的坑

学编程,总是逃不了要学“算法”,也总跳不开要学“设计模式”。 无论学习什么语言,设计模式始终是我们必须掌握的,这是程序员的基本功。 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。 项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都

实验楼--动手做实验,轻松学IT! 201

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

写文章要客观!

<br />  最近在优快云上看到文章越来越伤胃口了,是不是就议论Baidu和Google哪个更好之类的,虽然一想到百度的竞价排名,就难以打开其主页,但是,每当路过百度大厦时,我还是带着尊重的精神看待中国难得的发展很好的公司。而优快云对语言的讨论终究是那么让人大跌眼镜,今天说Java繁杂无比, 框架众多,前途不好,又会说Go语言风光不再。。。。<br />  在这里我们需要的是客观的看待事情,像优快云主页上的文章是程序员的小性子。我喜欢Java,但是,不习惯在不了解其他语言的时候进行攻击,而且Go很可

Chatopera 964

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深圳程序员职业发展路径与技术栈趋势分析

程序员作为数字经济的核心人才,其职业发展遵循技术深度与业务广度双轨并进的规律。从技术原理看,现代开发需要掌握云原生、微前端等架构思想,并理解分布式系统设计原则。在工程实践层面,深圳地区呈现Java生态稳固与Go语言崛起的双轨态势,云原生技术栈(Kubernetes+Docker)已成为基础能力要求。职业发展路径通常分为技术专家、管理路线和跨界转型三大方向,其中架构设计能力和商业敏感度是突破P7/P8瓶颈的关键。面对Web3.0和大模型应用的技术浪潮,建议开发者采用T型学习法,在保持1-2个技术深度的同时拓展

weixin_30731305的博客 412

Java、C语言、Python、PHP、C#、C++现代编程语言的核心特性与应用场景深度剖析

这些特性使Java长期以来成为企业级应用开发的首选,尤其是在大规模、分布式、高并发的后端系统(如Apache Hadoop、Kafka)、大型Web应用服务器(如Spring框架)、Android移动应用开发以及金融、电信等关键业务领域中。其核心特性包括直接嵌入HTML的能力、简单的部署方式、与多种数据库(尤其是MySQL)的原生集成、以及庞大的Web开发框架生态(如Laravel, Symfony)。其核心特性在于提供了对内存的底层直接访问(如指针操作)、简洁的关键字和运算符、以及高度可移植的编译器。

z45658的博客 684

腾讯?百度?程序员大厂实习经历经验谈

点击上方“程序人生”,选择“置顶公众号”第一时间关注程序猿(媛)身边的故事图片源自:Westworld Season 2作者大胜归来对于即将面临实习或毕业,步入社会的各位...

程序人生的博客 1万+

【每天一个AI大模型知识点】LangChain、Dify、n8n、Coze框架对比

本文对比分析了四大AI开发框架(LangChain、Dify、n8n、Coze)的核心特点与适用场景。LangChain以深度定制能力见长,适合复杂应用开发;Dify提供零代码快速上线方案;n8n专注于流程自动化集成;Coze则针对中文场景深度优化。文章提出了多维选型矩阵,建议根据定制深度、开发速度、中文支持等需求选择最合适框架,并预测未来AI开发将趋向Agent能力增强、门槛降低和生态融合三大方向。核心结论强调"没有最好,只有最合适"的选型理念。

yang_xs的博客(只讲干货) 943

C语言在现代软件开发中的核心地位与未来发展趋势分析

作为一门接近硬件底层的编译型语言,C语言以其无可比拟的执行效率、精准的内存控制和跨平台特性,在现代软件开发的诸多关键领域扮演着不可或缺的核心角色。C语言将更多地扮演“高性能计算核心”或“底层库”的角色,通过FFI被Python、Rust、Go等高级语言调用,发挥其性能优势,而将复杂的业务逻辑和安全性交由更现代的语言处理。未来,C语言的进化将更多地依赖于工具的辅助,例如更先进的静态分析工具、模糊测试技术和编码规范,以帮助开发者编写更安全的代码。展望未来,C语言的发展将呈现挑战与机遇并存的态势。

tqt_xy的博客 767

【转】百万年薪挖了p8,难道是水货?

大厦新搬进来一家创业公司,老板红光满面地提着果篮上楼拜访,说是刚拿到了投资人的钱,正准备扩充团队大干一场。那个时候的他踌躇满志,顾盼生辉。当时我想,能在这个大环境下拿到投资的公司,做的产品应该是有前景的。没想到几天后在电梯遇见时,却发现这位老板已经没有了往昔的风采,整天愁容满面。他在电梯看到我以后问道:“我记得你们是做技术媒体的吧,有个问题想请教一下。”原来他烦心的症结在于:我们公司拿到...

weixin_30457881的博客 166
上一篇: 《快学 Go 语言》第 7 课 —— 诱人的烤串
下一篇: 发自肺腑深入肌肤 —— 一位武汉老程序员的自白
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值