新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1、服务器编程:以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
创新互联主打移动网站、成都网站设计、网站制作、网站改版、网络推广、网站维护、申请域名、等互联网信息服务,为各行业提供服务。在技术实力的保障下,我们为客户承诺稳定,放心的服务,根据网站的内容与功能再决定采用什么样的设计。最后,要实现符合网站需求的内容、功能与设计,我们还会规划稳定安全的技术方案做保障。
2、凳旁蠢分布式系统、数据库代理器、中间件:例如Etcd。
3、网络编程:这一块目前应用最广,包括Web应用、API应用、下载应用,而且Go内置的net/http包基本上把我们平常用到的网络功能都实现了。
4、开发云平台:目前国外很多云平台在采用Go开发,我们所熟知的七牛云、华为云等等都有使用Go进行开发并且开源的成型的产品。
5、区块链:目前有一种说法,技术从业人员把Go语言称作为区块链行业启销的开发语言。如果大家学习区块链技术的话,就会发现现在有很多很多的区块链的系统和应用都是采用Go进行开发的,比如ehtereum是目前知名度最大的公链,再比如fabric是目前最知名的联盟链,两枣陪者都有go语言的版本,且go-ehtereum还是以太坊guan方推荐的版本。
自1.0版发布以来,go语言引起了众多开发者的关注,并得到了广泛的应用。go语言简单、高效、并发的特点吸引了许多传统的语言开发人员,其数量也在不断增加。
使用 Go 语言开发的开源项目非常多。早期的 Go 语言开源项目只是通过 Go 语言与传统项目进行C语言库绑定实现,例如 Qt、Sqlite 等。
后期的很多项目都使用 Go 语言进行重新原生实现,这个过程相对于其他语言要简单一些,这也促成了大量使用 Go 语言原生开发项目的出现。
一般命令
所谓一般命册汪令,就是在一定时间内会执行完的命令。比如 grep, cat 等等。 执行命令的步骤是:连接,执行,获取结果
连接
连接包含了认证,可以使用 password 或者 sshkey 2种方式来认证。下面的示例为了简单,使用了密码认证的方式来完成连接。
import (
"fmt"
"time"
"golang.org/x/crypto/ssh"
)
func connect(user, password, host string, port int) (*ssh.Session, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
session *ssh.Session
err error
)
// get auth method
auth = make([]ssh.AuthMethod, 0)
auth = append(auth, ssh.Password(password))
clientConfig = ssh.ClientConfig{
User: user,
Auth: auth,
Timeout: 30 * time.Second,
}
// connet to ssh
addr = fmt.Sprintf("%s:%d", host, port)
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create session
if session, err = client.NewSession(); err != nil {
return nil, err
}
return session, nil
}
连接的方法很简单,只要提供登录主机的 用户*, *密码*, *主机名或者IP*, *SSH端口
执行,命令获取结果
连接成功后,执行命令很简单
import (
"fmt"
"log"
"os"
"time"
"golang.org/x/crypto/ssh"州迹仔
)
func main() {
session, err := connect("root", "xxxxx", "127.0.0.1", 22)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.Run("ls /; ls /abc")
}
上面代码运行之后,虽然命令正常执行了,但是没有正常输出的结果,也没有异常输出的结果。 要想显示结果,需要将 session 的 Stdout 和 Stderr 重定向 修改 func main 为如下:
func main() {
session, err := connect("root", "xxxxx", "127.0.0.1", 22)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Run("ls /; ls /abc")
}
这样就能在屏幕上显示正州渗常,异常的信息了。
交互式命令
上面的方式无法远程执行交互式命令,比如 top , 远程编辑一个文件,比如 vi /etc/nginx/nginx.conf 如果要支持交互式的命令,需要当前的terminal来接管远程的 PTY。
func main() {
session, err := connect("root", "olordjesus", "dockers.iotalabs.io", 2210)
if err != nil {
log.Fatal(err)
}
defer session.Close()
fd := int(os.Stdin.Fd())
oldState, err := terminal.MakeRaw(fd)
if err != nil {
panic(err)
}
defer terminal.Restore(fd, oldState)
// excute command
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin
termWidth, termHeight, err := terminal.GetSize(fd)
if err != nil {
panic(err)
}
// Set up terminal modes
modes := ssh.TerminalModes{
ssh.ECHO: 1, // enable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// Request pseudo terminal
if err := session.RequestPty("xterm-256color", termHeight, termWidth, modes); err != nil {
log.Fatal(err)
}
session.Run("top")
}
总结
好了,这样就可以执行交互式命令了,比如上面的 top 也可以通过 vi /etc/nginx/nignx.conf 之类的命令来远程编辑文件。
参考:
Goroutine并发调度模型深度解析手撸一个协程池
Golang 的 goroutine 是如闹没何实现的?
Golang - 调度剖析【第二部分】
OS线程初始栈为2MB。Go语言中,每个goroutine采用动态扩容方式,初始2KB,按需增长,最大1G。此外GC会收缩栈空间。
BTW,增长扩容都是有代价的,需要copy数据到新的stack,所以初始2KB可能有些性能问题。
更多关于stack的内容,可以参见大佬的文章。 聊一聊goroutine stack
用户线程的调度以及生命周期管理都是用户层面含兄,Go语言自己实现的,不借助OS系统调用,减少系统资源消耗。
Go语言采用两级线程模型,即用户线程与内核线程KSE(kernel scheduling entity)是M:N的。最终goroutine还是会交给OS线程执行,但是需要一个中介,提供上下文。这就是G-M-P模型
Go调度器有两个不同的运行队列:
go1.10\src\runtime\runtime2.go
Go调度器根据事件进行上下文切换。
调度的液老纳目的就是防止M堵塞,空闲,系统进程切换。
详见 Golang - 调度剖析【第二部分】
Linux可以通过epoll实现网络调用,统称网络轮询器N(Net Poller)。
文件IO操作
上面都是防止M堵塞,任务窃取是防止M空闲
每个M都有一个特殊的G,g0。用于执行调度,gc,栈管理等任务,所以g0的栈称为调度栈。g0的栈不会自动增长,不会被gc,来自os线程的栈。
go1.10\src\runtime\proc.go
G没办法自己运行,必须通过M运行
M通过通过调度,执行G
从M挂载P的runq中找到G,执行G