强类型语言有它的优势,但也有不便利的地方,最典型的就是类型转换。Golang 作为一门强类型语言,而且不支持隐式类型转换,因此这个问题更突出。虽然 Go 提供了不少方式进行类型转换,包括相关的标准库,比如 strconv 包。
然而,strconv 包使用没那么方便,比如 "8" 转为 int 类型:
s := "8"
i, err := strconv.Atoi(s)
你必须对 err 进行处理,因为返回两个值,没法直接将结果传递给接收 int 参数的函数,使用不方便。
今天给大家介绍一个第三方库,专门处理类型转换的问题。
01 为什么需要类型转换
有一些场景会需要使用类型转换:
从 yaml、toml、jso...
日期:2022-11-25 03:47:11
阅读:892
前言
先来看一道面试题:
对已经关闭的 chan 进行读写,会怎么样?为什么?
在上一篇学习 Go 协程的文章中,知道 go 关键字可以用来开启一个 goroutine 进行任务处理,但多个任务之间如果需要通信,就需要用到通道(channel)了。
一、Channel的定义
声明并初始化一个通道,可以使用 Go 语言的内建函数 make,同时指定该通道类型的元素类型,下面声明了一个 chan int 类型的 channel:
ch := make(chan int)
二、Channel的操作
发送(写):发送操作包括了“复制元素值”和“放置副本到通道内部”这两个步骤。即:进入通道的并不是操作符右...
日期:2022-11-25 03:47:10
阅读:857
Switch简介
Go的switch的基本功能和C、Java类似:
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
匹配项后面也不需要再加 break。
特点:
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case
重点介绍Go当中的Switch的两个特别点:**
表达式判断为true还需要执行后面的 case,可以使用 fallthrough
type-switch 来判断某个 interface 变量中实际存储的变量类型
fallthrough
特点:
强制执行后面的 c...
日期:2022-11-25 03:47:10
阅读:872
说明
在golang中,时间转换都会通过Time类型做一系列转换。主要包含,时间戳和时间字符串,时间字符串转换成另外的格式。总之所有的转换都是通过Time类型做中间转换。参考文档:https://golang.org/pkg/time/
操作
1,获取当前时间
t1 := time.Now() // 返回的是时间Time类型
fmt.Println(t1, reflect.TypeOf(t1))
2,获取指定时间
t4 := time.Date(2019, 9, 30, 14, 28, 26, 23, time.Local) // 返回时间格式T...
日期:2022-11-25 03:47:09
阅读:869
1. 需求
要求统计1-200000的数字中,哪些是素数?这个问题在本章开篇就提出来了,可以使用goroutine和channel来完成
2.分析思路
传统的方法,就是使用一个循环,循环的判断各个数是不是素数【ok】
使用并发/并行的方式,将统计素数的任务分配给多个(x个)goroutine去完成,完成任务时间短
分析思路图:
代码实现:
package main
import (
"fmt"
"time"
)
// 需求:
// 要求统计1-200000的数字,哪些是素数?这个问题在本章开篇就提出了,现在我们有goroutine和channel的知识后,就可以完成了【测试数据:...
日期:2022-11-25 03:47:09
阅读:850
一、需求
实现二级缓存
程序运行起来后提示:“请输入命令:”,如果输入getall,查询并显示所有人员的信息
第一次时查询mysql并将结果缓存在redis,设置60秒的过期时间
以后的每次查询,如果redis有数据就从redis加载,没有则重复上一步的操作
二、实现连接Mysql并执行查询语句
先实现需求二,当输入命令getall时,查询并显示所有人员的信息。
package main
import (
"fmt"
_"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type...
日期:2022-11-25 03:47:08
阅读:903
哈希算法
md5
128bit,16字节
如:md5 (“hello world!”) = fc3ff98e8c6a0d3087d515c0473f8677 // 32位16进制数字
func Test(t *testing.T) {
//方法一
str := "hello world!"
has := md5.Sum([]byte(str))
md5str1 := fmt.Sprintf("%x", has) //将[]byte转成16进制
t.Log(md5str1)
//方法二
w := md5.New()
io.WriteString(w, str)...
日期:2022-11-25 03:47:08
阅读:896
本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下
首先, 我定义了三个测试的中间件 Middleware1,2,3 如下
func Middleware1(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("M1...
日期:2022-11-25 03:47:07
阅读:860
Go 协程超时控制
Select 阻塞方式
Context 方式
先说个场景:
假设业务中 A 服务需要调用 服务B,要求设置 5s 超时,那么如何优雅实现?
Select 超时控制
考虑是否可以用 select + time.After 方式进行实现
这里主要利用的是通道在携程之间通信的特点,当程序调用成功后,会向通道中发送信号。没调用成功前,通道会阻塞。
select {
case res := <-c2:
fmt.Println(res)
case <-time.After(time.Second * 3):
fmt.Println("timeout 2")...
日期:2022-11-25 03:47:07
阅读:857
算数运算符
算数运算符和C语言几乎一样
运算符
描述
实例
+
相加
A + B
-
相减
A - B
*
相乘
A * B
/
相除
B / A
%
求余
B % A
++
自增
A++
–
自减
A–
注意点:
只有相同类型的数据才能进行运算...
日期:2022-11-25 03:47:06
阅读:900
普通指针
和C语言一样, 允许用一个变量来存放其它变量的地址, 这种专门用于存储其它变量地址的变量, 我们称之为指针变量
和C语言一样, Go语言中的指针无论是什么类型占用内存都一样(32位4个字节, 64位8个字节)
package main
import (
"fmt"
"unsafe"
)
func main() {
var p1 *int;
var p2 *float64;
var p3 *bool;
fmt.Println(unsafe.Sizeof(p1)) // 8
fmt.Println(unsafe.Sizeof(p2)) // 8
fmt.P...
日期:2022-11-25 03:47:05
阅读:879
异常处理
程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常
golang中提供了两种处理异常的方式
一种是程序发生异常时, 将异常信息反馈给使用者
一种是程序发生异常时, 立刻退出终止程序继续运行
打印异常信息
Go语言中提供了两种创建异常信息的方式
方式一: 通过fmt包中的Errorf函数创建错误信息, 然后打印
package main
import "fmt"
func main() {
// 1.创建错误信息
var err error = fmt.Errorf("这里是错误信息")
// 2.打印错...
日期:2022-11-25 03:47:05
阅读:856
查看官方文档,官方自带的演示:
// 官方演示
package main
import (
"archive/tar"
"bytes"
"fmt"
"io"
"log"
"os"
)
func main() {
// 将若干文件写入压缩文档
// 这边源文件是直接写在代码里哈,然后也没有输出一个文档
// 后面会演示源文件进行压缩,然后输出一个tar.gz的压缩文档
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
var files =...
日期:2022-11-25 03:47:04
阅读:900
一、语言结构和注意事项
package main // 声明 main 包,表明当前是一个可执行程序
import "fmt" // 导入内置的fmt包
func main(){ // main函数,是程序执行的入口
fmt.Println("Hello World!") // 在终端打印 Hello World!
}
需要注意的是包裹代码的左大括号{ 在Golang中不能单独成为一行,例如下面这样:
func main()
{ // 会报错
fmt.Println("Hello World!") // 在终端打印 Hello World!
}
除此之外,Go...
日期:2022-11-25 03:47:03
阅读:879
一.序
单从库名大概就能猜出其作用。sync.Once使用起来很简单, 下面是一个简单的使用案例
package main
import (
"fmt"
"sync"
)
func main() {
var (
once sync.Once
wg sync.WaitGroup
)
for i := 0; i < 10; i++ {
wg.Add(1)
// 这里要注意讲i显示的当参数传入内部的匿名函数
go func(i int) {
defer wg.Done()
// fmt.Println("once", i)...
日期:2022-11-25 03:47:03
阅读:871
前言
今天的文章比较基础,但却是必须掌握的,而且本文有些内容,也许你之前没想过。希望这篇文章能够让你理解环境变量并掌握 Go 环境变量相关操作。
01 从安装 Go 说起
其实不止是安装 Go,其他语言一本也会有类似的问题。一般来说,安装完 Go 后,会建议将 go 可执行程序配置到 PATH 环境变量中。
比如我本地的 PATH 环境变量的值:
$ echo $PATH
/Users/xuxinhua/.go/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Wireshark.app/Contents/M...
日期:2022-11-25 03:47:02
阅读:900
先来看这样一段代码,所存在的问题:
var wg sync.WaitGroup
var x int64
func main() {
wg.Add(2)
go f()
go f()
wg.Wait()
fmt.Println(x) // 输出:12135
}
func f() {
for i:=0;i<10000;i++ {
x = x+1
}
wg.Done()
}
这里为什么输出是 12135(不同的机器结果不一样),而不是20000。
因为 x 的赋值,总共分为三个步骤:取出x的值、计算x的结果、给x赋值。那么由于对于f函数的调用采用了gorouti...
日期:2022-11-25 03:47:02
阅读:795
前言
在 Golang 中 map 不是并发安全的,自 1.9 才引入了 sync.Map ,sync.Map 的引入确实解决了 map 的并发安全问题,不过 sync.Map 却没有实现 len() 函数,如果想要计算 sync.Map 的长度,稍微有点麻烦,需要使用 Range 函数。
map 并发操作出现问题
func main() {
demo := make(map[int]int)
go func() {
for j := 0; j < 1000; j++ {
demo[j] = j
}
}()
go func() {
for j := 0; j &...
日期:2022-11-25 03:47:02
阅读:865