Go 语言是一门充满学问的语言,开发者如果不充分了解这些学问,一不小心就会掉入“陷阱”,这里来分享一个经典的nil != nil
的问题。
在 Go 语言中,"接口值为 nil 但不等于 nil" 的现象源于接口类型独特的底层表示结构。
这看似矛盾的现象可以通过理解接口的内部实现来理解。
Go 语言是一门充满学问的语言,开发者如果不充分了解这些学问,一不小心就会掉入“陷阱”,这里来分享一个经典的nil != nil
的问题。
在 Go 语言中,"接口值为 nil 但不等于 nil" 的现象源于接口类型独特的底层表示结构。
这看似矛盾的现象可以通过理解接口的内部实现来理解。
在 Go语言中,字节序(Endianness)是处理多字节数据类型(如int32、uint64等)在内存存储或网络传输时字节排列顺序的核心概念。Go通过标准库encoding/binary提供对大小端序的完整支持。
其实,我第一次知道字节序还是在五年前,当时是需要和一位C/C++
大佬做TCP
数据对接,在大佬的指导下,才对字节序有了一定的了解,除此之外就很少接触要使用字节序的场景。
大端序(Big-Endian):高位字节存储在低地址(或先传输)。
示例:0x12345678存储为 []byte{0x12, 0x34, 0x56, 0x78}。
在 Go 语言中要初始化一个数组可有很多种方式,可以直接指定长度不指定元素var arr [5]int
,也可以显示初始化数组指定长度并赋值arr := [5]int{1, 2, 3, 4, 5}
,还可以按索引指定部分索引的值arr := [5]int{0: 10, 3: 40}
。
但是刚刚刷到一道面试题,题目是这样的:
在 Go 项目中使用go mod
作为依赖管理工具,go.mod
文件是其核心配置文件。
一般情况下,go.mod
的配置项主要有:module
go
require
,大概结构如下:
提起 Go 语言中的rune
类型,相信大家对它并不陌生。虽然它并不常用,但在我的印象里,用得最多的就是用它来处理中文字符串截取。
没错,多语言的字符串处理就是rune
的强项。
今天网上刷到一个网友的提问:在 Go 语言中两个 interface{} 可以比较吗?我想了一下,在我的项目中,几乎很少去直接比较两个interface{}
类型的变量,但真要比较的话,答案是肯定的,两个interface{}
肯定可以比较,但是多少得注意一下细节。随后,我就在网上查阅了相关资料,在这里和大家详细分享一下。
interface{}
不仅仅用来表示接口,它是一个动态类型,可以用来表示任意类型,也有一个别名any
。这里所说的比较是指用==
或!=
比较。
在官网Comparison operators中有这么一句话:
很多人都说init()
函数在 Go 语言中是一种神奇的存在,那么它到底神奇在哪里呢?这里就来聊一聊在 Go 语言中 init()
函数的作用以及它的执行顺序。
顾名思义,init
是英语单词"initialization"的缩写形式,意思是初始化的意思,用来执行一些初始化操作,它在入口函数main()
之前执行,并且一个包中甚至一个文件中,可以有多个init()
函数,没有参数和返回值。
话不多说,这里直接上代码验证一下:
在Go
中所说的空结构体就是struct{}
,它是一种特殊的存在,可能你在项目中看到过,但并没有深入的了解它的应用场景,这里结合自己平时项目中的经验,介绍一下空结构体(struct{})的一些应用场景。
Go
语言中的空结构体(struct{})是一种零内存占用的特殊类型,其所有实例可能共享同一内存地址(zerobase),它不包含任何字段,但却有很多应用场景。
紧接上文,这里就来验证一下,空结构体的内存地址是否相同,以及内存占用大小:
在面向对象编程中,接口
是一个重要概念,它是一种契约
,它定义了对象应该具备的方法。一个接口
可以有多重实现,它的所有实现都必须满足接口
所有约定的方法。并不是所有编程语言都有接口,例如在C
、Python
、Ruby
中是没有内置的接口机制,但在大多数编程语言中都有接口
的概念,一般用interface
来标记。
Java
和Go
都是有内置的接口
的机制,但在接口实现上却不尽相同。这些区别主要是接口定义、接口实现、约束机制和应用场景等方面,下面就这些不同进行逐一比较。
这里我们探讨的信号不是手机信号,也不是Wifi、蓝牙等信号。信号是 Linux、Unix以及其他 POSIX 兼容的操作系统中进程间通讯的一种机制,用于告知进程一个事件已经发生。
更准确的来说,这里所说的信号是在 Linux 系统中通过kill
及其相关命令向指定进程发送的控制信号。在 Go 应用开发中,正确处理这些信号非常有必要。
在 Linux 操作系统中系统信号很多类型,这里简要列一些常用的系统信号:
| 信号 | 触发方式 | 用途 |
在使用 Golang 做并发编程的过程中,锁
是开发中必不可少的工具之一,它可以避免多协程对共享资源的并发读写,通过加锁来解决对共享资源的并发控制。
在 Go 语言中提供了互斥锁sync.Mutex{}
和读写锁sync.RWMutex{}
。他们都实现了sync.Locker
接口:
Go语言是Google推出的一个全新的编程语言,在2009年11月正式对外发布。经过快速迭代,2012年3月28日,Go发布第⼀个正式的稳定版本。
出身名门的go语言,吸收了其他语言的特点,是一种并发的、带垃圾回收的、快速编译的语言。
defer
panic
recover
错误处理机制java
php
里的反射(Reflection)类似ThinkGo 是一个轻量级的 Go 语言 MVC 框架,目前支持路由、中间件、控制器、请求、响应、Session、视图、日志、缓存、ORM等 web 框架应该具备的基本功能,ThinkGo致力于让代码简洁且富于表达力,帮助开发者快速构建一个 Web 应用。
前置
/后置
中间件RFC 5424
规范。go get github.com/thinkoner/thinkgo
package main
import (
"github.com/thinkoner/thinkgo"
"fmt"
"github.com/thinkoner/thinkgo/router"
"github.com/thinkoner/thinkgo/context"
)
func main() {
app := thinkgo.BootStrap()
app.RegisterRoute(func(route *router.Route) {
route.Get("/", func(req *context.Request) *context.Response {
return thinkgo.Text("Hello ThinkGo !")
})
route.Get("/ping", func(req *context.Request) *context.Response {
return thinkgo.Json(map[string]string{
"message": "pong",
})
})
// Dependency injection
route.Get("/user/{name}", func(req *context.Request, name string) *context.Response {
return thinkgo.Text(fmt.Sprintf("Hello %s !", name))
})
})
// listen and serve on 0.0.0.0:9011
app.Run()
}
goquery是一个使用go语言写成的HTML解析库,可以让你像jQuery那样的方式来操作DOM文档,使用起来非常的简便。
闲话少说,直接上代码:
package main
import (
"gopkg.in/mgo.v2"
"github.com/PuerkitoBio/goquery"
"log"
"gopkg.in/mgo.v2/bson"
)
type Article struct {
Title string
Decription string
Image string
Author string
Time string
}
func main() {
getArticle()
}
func getArticle() {
//连接MongoDB数据库
session, err := mgo.Dial("")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("article")
//使用goquery开始抓取
doc, err := goquery.NewDocument("http://weixin.sogou.com/")
if err != nil {
log.Fatal(err)
}
//编辑文章节点
doc.Find(".news-list li").Each(func(i int, contentSelection *goquery.Selection) {
//文章标题
title := contentSelection.Find(".txt-box h3 a").Text()
decription := contentSelection.Find(".txt-box .txt-info").Text()
image, _ := contentSelection.Find(".img-box img").Attr("src")
author := contentSelection.Find(".txt-box .account").Text()
time, _ := contentSelection.Find(".txt-box .s-p").Attr("t")
result := Article{}
//是否已经保存过该文章
err = c.Find(bson.M{"title": title}).One(&result)
if err != nil {
log.Println("第", i+1, "篇文章:", title)
//保存至数据库
err = c.Insert(&Article{title, decription, image, author, time})
if err != nil {
panic(err)
}
}
log.Println(result)
})
}
MongoDB查看爬取到的文章:
专业企业官网建设,塑造企业形象,传递企业价值
系统软件开发,用心思考,用心设计,用心体验
打破技术瓶颈,让不堪重负的项目起死回生
构建全渠道一体化运营能力,实现全链路数字化
文案撰写、营销策划,专注品牌全案
一站式解决企业互联网营销痛点和难题
以技术的力量,改变互联网
联系我们