新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Go 语言又称为 golang, 是由 Google 最初开发的一种开源编程语言,其在设计时就遵循了简单、安全和速度的 3 大原则。Go 语言具有多种调试、测试、分析和代码审查工具,如今 Go 语言和工具已在大多数 Linux 发行版本的源库中进行提供,本文我就来说明如何为 Linux 安装 Go 语言。Ubuntu、Debian或Linux Mint安装Go语言基于 Debian的 Linux 发行版本都可以使用 apt-get 命令来进行安装:sudo apt-get install golang要查看当前系统安装的 Go 语言版本可以使用如下命令:go version由于 Go 代码必需保存在 workspace(工作区)中,所以我们必需在 Home 目录(例如 ~/workspace)创建一个workspace 目录并定义 GOPATH 环境变量指向该目录,这个目录将被 Go 工具用于保存和编辑二进制文件。mkdir ~/workspaceecho 'export GOPATH="$HOME/workspace"' ~/.bashrcsource ~/.bashrc根据不同的需要,我们可以使用 apt-get 安装 Go tools:sudo apt-cache search golangFedora、CentOS或RHEL安装Go语言基于 Red Hat 的 Linux 发行版本都可以使用 yum 命令来进行安装:sudo yum install golang要查看当前系统安装的 Go 语言版本可以使用如下命令:go version接下来还是在 Home 目录(例如 ~/workspace)创建一个 workspace 目录并定义 GOPATH 环境变量指向该目录,这个目录将被 Go 工具用于保存和编辑二进制文件。mkdir ~/workspaceecho 'export GOPATH="$HOME/workspace"' ~/.bashrcsource ~/.bashrc根据不同的需要,我们可以使用 yum 安装 Go tools:yum search golang为Linux手动安装Go语言由于大家使用的 Linux 源不尽相同,也不见得是最新版本或需要版本的 Go 语言包,所以我们说一下如何手动安装指定版本。下载 Go 语言文件64-bit Linuxwget Linuxwget 下载地址:解压二进制文件到 /usr/local 目录sudo tar -xzf go1.4.2.linux-xxx.tar.gz -C /usr/local使用 vi 在环境变量配置文件 /etc/profile 中增加如下内容:export PATH=$PATH:/usr/local/go/bin检查 Go 语言版本go version定义 GOPATH 环境变量到 workspace 目录export GOPATH="$HOME/workspace
创新互联建站从2013年创立,先为耀州等服务建站,耀州等地企业,进行企业商务咨询服务。为耀州企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
python和go语言的区别
1、语法
Python的语法使用缩进来指示代码块。Go的语法基于打开和关闭括号。
2、范例
Python是一种基于面向对象编程的多范式,命令式和函数式编程语言。它坚持这样一种观点,即如果一种语言在某些情境中表现出某种特定的方式,理想情况下它应该在所有情境中都有相似的作用。但是,它又不是纯粹的OOP语言,它不支持强封装,这是OOP的主要原则之一。
Go是一种基于并发编程范式的过程编程语言,它与C具有表面相似性。实际上,Go更像是C的更新版本。
3、并发
Python没有提供内置的并发机制,而Go有内置的并发机制。
4、类型化
Python是动态类型语言,而Go是一种静态类型语言,它实际上有助于在编译时捕获错误,这可以进一步减少生产后期的严重错误。
5、安全性
Python是一种强类型语言,它是经过编译的,因此增加了一层安全性。Go具有分配给每个变量的类型,因此,它提供了安全性。但是,如果发生任何错误,用户需要自己运行整个代码。
6、管理内存
Go允许程序员在很大程度上管理内存。而,Python中的内存管理完全自动化并由Python VM管理;它不允许程序员对内存管理负责。
7、库
与Go相比,Python提供的库数量要大得多。然而,Go仍然是新的,并且还没有取得很大进展。
8、速度:
Go的速度远远超过Python。
Go语言作为出现比较晚的一门编程语言,在其原生支持高并发、云原生等领域的优秀表现,像目前比较流行的容器编排技术Kubernetes、容器技术Docker都是用Go语言写的,像Java等其他面向对象的语言,虽然也能做云原生相关的开发,但是支持的程度远没有Go语言高,凭借其语言特性和简单的编程方式,弥补了其他编程语言一定程度上的不足,一度成为一个热门的编程语言。
最近在学习Go语言,我之前使用过C#、Java等面向对象编程的语言,发现其中有很多的编程方式和其他语言有区别的地方,好记性不如烂笔头,总结一下,和其他语言做个对比。这里只总结差异的地方,具体的语法不做详细的介绍。
种一棵树最好的时间是十年前,其次是现在。
3)变量初始化时候可以和其他语言一样直接在变量后面加等号,等号后面为要初始化的值,也可以使用变量名:=变量值的简单方式
3)变量赋值 Go语言的变量赋值和多数语言一致,但是Go语言提供了多重赋值的功能,比如下面这个交换i、j变量的语句:
在不支持多重赋值的语言中,交换两个变量的值需要引入一个中间变量:
4)匿名变量
在使用其他语言时,有时候要获取一个值,却因为该函数返回多个值而不得不定义很多没有的变量,Go语言可以借助多重返回值和匿名变量来避免这种写法,使代码看起来更优雅。
假如GetName()函数返回3个值,分别是firstName,lastName和nickName
若指向获得nickName,则函数调用可以这样写
这种写法可以让代码更清晰,从而大幅降低沟通的复杂度和维护的难度。
1)基本常量
常量使用关键字const 定义,可以限定常量类型,但不是必须的,如果没有定义常量的类型,是无类型常量
2)预定义常量
Go语言预定义了这些常量 true、false和iota
iota比较特殊,可以被任务是一个可被编译器修改的常量,在每个const关键字出现时被重置为0,然后在下一个const出现之前每出现一个iota,其所代表的数字会自动加1.
3)枚举
1)int 和int32在Go语言中被认为是两种不同类型的类型
2)Go语言定义了两个浮点型float32和float64,其中前者等价于C语言的float类型,后者等价于C语言的double类型
3)go语言支持复数类型
复数实际上是由两个实数(在计算机中使用浮点数表示)构成,一个表示实部(real)、一个表示虚部(imag)。也就是数学上的那个复数
复数的表示
实部与虚部
对于一个复数z=complex(x,y),就可以通过Go语言内置函数real(z)获得该复数的实部,也就是x,通过imag(z)获得该复数的虚部,也就是y
4)数组(值类型,长度在定义后无法再次修改,每次传递都将产生一个副本。)
5)数组切片(slice)
数组切片(slice)弥补了数组的不足,其数据结构可以抽象为以下三个变量:
6)Map 在go语言中Map不需要引入任何库,使用很方便
Go循环语句只支持for关键字,不支持while和do-while
goto语句的语义非常简单,就是跳转到本函数内的某个标签
今天就介绍到这里,以后我会在总结Go语言在其他方面比如并发编程、面向对象、网络编程等方面的不同及使用方法。希望对大家有所帮助。
函数式语言
Elixir
Elixir 比 Erlang 更容易编写,具有 Haskell 等语言的函数式编程概念。Elixir是基于Erlang 虚拟机的,其广为人知的特点是运行低延时、分布式、可容错的系统,并成功用于Web开发与嵌入式软件领域。
Elm
Elm是一种用于构建 Web 应用程序的函数式语言。业内一般认为,它适用于创建高可交互应用,例如复杂的用户界面,开发人员可以通过 Elm 快速编写富有表现力的系统。Elm 也以没有运行时异常而闻名。
PureScript
PureScript是一种可编译为 JavaScript 的纯函数式编程语言。与 Haskell 最相似的是,PureScript 最适合用于开发 Web 应用程序和服务器端应用程序。
PureScript 支持类型推断,与其他语言相比,需要明显类型注释要少得多。
Swift
Swift是一种由苹果公司开发的通用编译编程语言,最早的设想是替代上一代编程语言Objective-C ,过程中结合了Objective-C、Rust、Ruby 和 Python等语言的编程思想。目前Swift用于开发苹果自己的手机、服务器、台式机上的应用软件。
程序语言
Go
Go语言是由谷歌公司创造的类似C风格的语言。Go 比 C++ 或 Java 更简洁,比 Ruby 或 Python 更安全。
一些缺点: 编码要求严格。比如,不能混用符号和无符号整数。还有一个明显的遗漏,Go语言没有泛型和继承。
但Go语言的优势同样明显,简单且易于使用。Go语言擅长于网络和多线程方面的编程。
面向对象语言
DART
Dart同样来自谷歌公司具有C语言风格。Dart可以轻松编写JavaScript、Java for Android、本地机器代码或独立的 Dart 虚拟机。它还可以运行后端代码。
Dart 非常适合使用事件驱动代码构建用户界面。根据Dart 团队成员的说法,Dart的优势:可选的静态类型、最小的编译时错误和强大的内置编辑器。
Pony
Pony是一种基于无数据竞争类型和垃圾收集的语言,并使用 actor 模型以及称为引用功能的东西。
你可以把 Pony 想象成某种“Rust 遇上 Erlang”的复合体,没有锁,高并发是其主要优点。
Pony 的缺点是 API 稳定性低、很少有高质量的第三方库和有限的本地工具。
TypeScript
TypeScript是一个基于 JavaScript 静态类型定义构建,并由微软维护且开源编程语言。Visual Studio Code 或Visual Studio 是推荐的IDE编辑器,微软大厂的用户体验和错误检查也不用怀疑。
复合编程语言
Hack
Hack是一种作为 PHP 方言的 HipHop 虚拟机的编程语言。于 2014 年由Facebook创建,允许程序员同时使用静态和动态类型(也称为渐进类型),这为编码提供了灵活性。
Julia
Julia是一种高级通用编程语言,用于计算科学和数值分析。Julia 以动态类型和可重现的高性能特性而闻名。
Julia 在数据可视化和机器学习等方面都有大量用途。事实上,它被英国保险公司 Aviva 用于风险计算,纽约联邦储备银行用于金融建模,甚至气候建模联盟用于气候变化建模。它拥有Fortran、C++、R、Java、C 、Python等的接口,这使其成为最受追捧的新语言之一。
Kotlin
Kotlin是运行在 Java 虚拟机中的更快、更流畅的 Java 版本。它现在是Android 开发的首选语言。根据 Android 开发者网站显示,程序员正转而采用 Kotlin,因为该语言的样板代码更少,空指针异常更少,并且与 Java 有互操作性。
Kotlin 可用于在 iOS 和 Android 上运行的应用程序、不使用额外运行时或虚拟机。
Nim
Nim是一种优先考虑可读性的静态类型语言。通过结合多种语言的特性,Nim 为程序员提供了速度和易用性。
它带有 JavaScript 后端、分散的包管理、自动内存管理、C 和 C++ 库的绑定以及用于调试的回溯。作为一种语言,Nim 是有限的,但它包含一组元编程功能,如泛型、模板和宏,因此开发人员可以在避免冗长代码的同时以不同的风格工作。
OCaml作为此列表中较旧的语言,OCaml是一种多范式语言——既有函数式、命令式和类型安全,也具有面向对象功能。
OCaml 的一些优势:定义数据类型很容易。默认情况下,所有变量都是不可变的。API 稳定,具有良好的库向后兼容性。该语言还为独立应用程序提供自动内存管理和单独编译。
Reason
如果比JavaScript 更快、更简单且类型安全会怎样?
这就是创建Reason的 Facebook 开发者想要回答的问题。不过,他并没有从头开始构建一种新语言,而是采用了 OCaml,并将其调整为类似于 JavaScript。
Reason使用项目 BucketScript编译为 JavaScript,并且可以访问 80% 的 JavaScript 工具和生态系统。它还可以编译为准系统、iOS、Android 和微控制器。
Red
Red是一种最初旨在克服 Rebol 语言限制的编程语言。Red 于 2011 年推出,受 Rebol、Lua 和 Scala 等语言的影响,对高级和低级编程都很有用。
该语言可用于开发从高级 GUI 到低级操作系统的所有方面。Red 拥有人性化的语法、低内存占用和垃圾收集等优点。
Rust
Rust解决了一些与 Go 相同的问题,如系统级别的线程和进程安全,,但Rust 更像 C 风格的语法
但Rust语言的缺点:静态类型和缺乏垃圾收集
Rust可直接访问内存意味着程序员可以编写低级代码,如操作系统内核。Rust 也非常适合嵌入式设备、网络服务和命令行编写。
一、关于连接池
一个数据库服务器只拥有有限的资源,并且如果你没有充分使用这些资源,你可以通过使用更多的连接来提高吞吐量。一旦所有的资源都在使用,那么你就不 能通过增加更多的连接来提高吞吐量。事实上,吞吐量在连接负载较大时就开始下降了。通常可以通过限制与可用的资源相匹配的数据库连接的数量来提高延迟和吞 吐量。
如何在Go语言中使用Redis连接池
如果不使用连接池,那么,每次传输数据,我们都需要进行创建连接,收发数据,关闭连接。在并发量不高的场景,基本上不会有什么问题,一旦并发量上去了,那么,一般就会遇到下面几个常见问题:
性能普遍上不去
CPU 大量资源被系统消耗
网络一旦抖动,会有大量 TIME_WAIT 产生,不得不定期重启服务或定期重启机器
服务器工作不稳定,QPS 忽高忽低
要想解决这些问题,我们就要用到连接池了。连接池的思路很简单,在初始化时,创建一定数量的连接,先把所有长连接存起来,然后,谁需要使用,从这里取走,干完活立马放回来。 如果请求数超出连接池容量,那么就排队等待、退化成短连接或者直接丢弃掉。
二、使用连接池遇到的坑
最近在一个项目中,需要实现一个简单的 Web Server 提供 Redis 的 HTTP interface,提供 JSON 形式的返回结果。考虑用 Go 来实现。
首先,去看一下 Redis 官方推荐的 Go Redis driver。官方 Star 的项目有两个:Radix.v2 和 Redigo。经过简单的比较后,选择了更加轻量级和实现更加优雅的 Radix.v2。
Radix.v2 包是根据功能划分成一个个的 sub package,每一个 sub package 在一个独立的子目录中,结构非常清晰。我的项目中会用到的 sub package 有 redis 和 pool。
由于我想让这种被 fork 的进程最好简单点,做的事情单一一些,所以,在没有深入去看 Radix.v2 的 pool 的实现之前,我选择了自己实现一个 Redis pool。(这里,就不贴代码了。后来发现自己实现的 Redis pool 与 Radix.v2 实现的 Redis pool 的原理是一样的,都是基于 channel 实现的, 遇到的问题也是一样的。)
不过在测试过程中,发现了一个诡异的问题。在请求过程中经常会报 EOF 错误。而且是概率性出现,一会有问题,一会又好了。通过反复的测试,发现 bug 是有规律的,当程序空闲一会后,再进行连续请求,会发生3次失败,然后之后的请求都能成功,而我的连接池大小设置的是3。再进一步分析,程序空闲300秒 后,再请求就会失败,发现我的 Redis server 配置了 timeout 300,至此,问题就清楚了。是连接超时 Redis server 主动断开了连接。客户端这边从一个超时的连接请求就会得到 EOF 错误。
然后我看了一下 Radix.v2 的 pool 包的源码,发现这个库本身并没有检测坏的连接,并替换为新server{location/pool{content_by_lua_block{localredis=require"resty.redis"localred=redis:new()localok,err=red:connect("127.0.0.1",6379)ifnotokthenngx.say("failedtoconnect:",err)returnendok,err=red:set("hello","world")ifnotokthenreturnendred:set_keepalive(10000,100)}}}
发现有个 set_keepalive 的方法,查了一下官方文档,方法的原型是 syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size) 貌似 max_idle_timeout 这个参数,就是我们所缺少的东西,然后进一步跟踪源码,看看里面是怎么保证连接有效的。
function_M.set_keepalive(self,...)localsock=self.sockifnotsockthenreturnnil,"notinitialized"endifself.subscribedthenreturnnil,"subscribedstate"endreturnsock:setkeepalive(...)end
至此,已经清楚了,使用了 tcp 的 keepalive 心跳机制。
于是,通过与 Radix.v2 的作者一些讨论,选择自己在 redis 这层使用心跳机制,来解决这个问题。
四、最后的解决方案
在创建连接池之后,起一个 goroutine,每隔一段 idleTime 发送一个 PING 到 Redis server。其中,idleTime 略小于 Redis server 的 timeout 配置。连接池初始化部分代码如下:
p,err:=pool.New("tcp",u.Host,concurrency)errHndlr(err)gofunc(){for{p.Cmd("PING")time.Sleep(idelTime*time.Second)}}()
使用 redis 传输数据部分代码如下:
funcredisDo(p*pool.Pool,cmdstring,args...interface{})(reply*redis.Resp,errerror){reply=p.Cmd(cmd,args...)iferr=reply.Err;err!=nil{iferr!=io.EOF{Fatal.Println("redis",cmd,args,"erris",err)}}return}
其中,Radix.v2 连接池内部进行了连接池内连接的获取和放回,代码如下:
//Cmdautomaticallygetsoneclientfromthepool,executesthegivencommand//(returningitsresult),andputstheclientbackinthepoolfunc(p*Pool)Cmd(cmdstring,args...interface{})*redis.Resp{c,err:=p.Get()iferr!=nil{returnredis.NewResp(err)}deferp.Put(c)returnc.Cmd(cmd,args...)}
这样,我们就有了 keepalive 的机制,不会出现 timeout 的连接了,从 redis 连接池里面取出的连接都是可用的连接了。看似简单的代码,却完美的解决了连接池里面超时连接的问题。同时,就算 Redis server 重启等情况,也能保证连接自动重连。