问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

为什么要使用 Go 语言?Go 语言的优势在哪里?

发布网友 发布时间:2022-04-19 15:21

我来回答

4个回答

懂视网 时间:2022-05-02 23:20

db, err := sql.Open("mysql", "root:root@/uestcbook")

(1)sql.Open("mysql", "username:pwd@/databasename")

功能:返回一个DB对象,DB对象对于多个goroutines并发使用是安全的,DB对象内部封装了连接池。

实现:open函数并没有创建连接,它只是验证参数是否合法。然后开启一个单独goroutines去监听是否需要建立新的连接,当有请求建立新连接时就创建新连接。

注意:open函数应该被调用一次,通常是没必要close的。

 

(2)DB.Exec()

功能:执行不返回行(row)的查询,比如INSERT,UPDATE,DELETE

实现:DB交给内部的exec方法负责查询。exec会首先调用DB内部的conn方法从连接池里面获得一个连接。然后检查内部的driver.Conn实现了Execer接口没有,如果实现了该接口,会调用Execer接口的Exec方法执行查询;否则调用Conn接口的Prepare方法负责查询。

 

(3)DB.Query()

功能:用于检索(retrieval),比如SELECT

实现:DB交给内部的query方法负责查询。query首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用内部的queryConn方法负责查询。

 

(4)DB.QueryRow()

功能:用于返回单行的查询

实现:转交给DB.Query()查询

 

(5)db.Prepare()

功能:返回一个Stmt。Stmt对象可以执行Exec,Query,QueryRow等操作。

实现:DB交给内部的prepare方法负责查询。prepare首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用driverConn的prepareLocked方法负责查询。

Stmt相关方法:

st.Exec()

st.Query()

st.QueryRow()

st.Close()

 

(6)db.Begin()

功能:开启事务,返回Tx对象。调用该方法后,这个TX就和指定的连接绑定在一起了。一旦事务提交或者回滚,该事务绑定的连接就还给DB的连接池。

实现:DB交给内部的begin方法负责处理。begin首先调用DB内部的conn方法从连接池里面获得一个连接,然后调用Conn接口的Begin方法获得一个TX。

TX相关方法:

//内部执行流程和上面那些差不多,只是没有先去获取连接的一步,因为这些操作是和TX关联的,Tx建立的时候就和一个连接绑定了,所以这些操作内部共用一个TX内部的连接。

tx.Exec() 

tx.Query()

tx.QueryRow()

tx.Prepare()

tx.Commit()

tx.Rollback()

tx.Stmt()//用于将一个已存在的statement和tx绑定在一起。一个statement可以不和tx关联,比如db.Prepare()返回的statement就没有和TX关联。

 

几个主要struct的内部主要的数据结构

技术图片

 

(1)Exec 

result, err := db.Exec(
 "INSERT INTO users (name, age) VALUES (?, ?)",
 "gopher",
 27,
)

 

(2)Query 

rows, err := db.Query("SELECT name FROM users WHERE age = ?", age)
if err != nil {
 log.Fatal(err)
}
for rows.Next() {
 var name string
 if err := rows.Scan(&name); err != nil {
 log.Fatal(err)
 }
 fmt.Printf("%s is %d
", name, age)
}
if err := rows.Err(); err != nil {
 log.Fatal(err)
}

 

(3)QueryRow

var age int64
row := db.QueryRow("SELECT age FROM users WHERE name = ?", name)
err := row.Scan(&age)

 

 

(4)Prepared statements 

age := 27
stmt, err := db.Prepare("SELECT name FROM users WHERE age = ?")
if err != nil {
 log.Fatal(err)
}
rows, err := stmt.Query(age)
// process rows

 4. 事务

tx, err := db.Begin()
if err != nil {
 log.Fatal(err)
}

 5. 各种方式效率分析

问题:db.exec和statement.exec和tx.exec的区别?

实例如下:

package main

import (
 "strconv"
 "database/sql"
 _ "github.com/go-sql-driver/mysql"
 "fmt"
 "time"
 "log"
)

var db = &sql.DB{}

func init(){
 db,_ = sql.Open("mysql", "root:root@/book")
} 

func main() {
 insert()
 query()
 update()
 query()
 delete()
}

func update(){
 //方式1 update
 start := time.Now()
 for i := 1001;i<=1100;i++{
 db.Exec("UPdate user set age=? where uid=? ",i,i)
 }
 end := time.Now()
 fmt.Println("方式1 update total time:",end.Sub(start).Seconds())
 
 //方式2 update
 start = time.Now()
 for i := 1101;i<=1200;i++{
 stm,_ := db.Prepare("UPdate user set age=? where uid=? ")
 stm.Exec(i,i)
 stm.Close()
 }
 end = time.Now()
 fmt.Println("方式2 update total time:",end.Sub(start).Seconds())
 
 //方式3 update
 start = time.Now()
 stm,_ := db.Prepare("UPdate user set age=? where uid=?")
 for i := 1201;i<=1300;i++{
 stm.Exec(i,i)
 }
 stm.Close()
 end = time.Now()
 fmt.Println("方式3 update total time:",end.Sub(start).Seconds())
 
 //方式4 update
 start = time.Now()
 tx,_ := db.Begin()
 for i := 1301;i<=1400;i++{
 tx.Exec("UPdate user set age=? where uid=?",i,i)
 }
 tx.Commit()
 
 end = time.Now()
 fmt.Println("方式4 update total time:",end.Sub(start).Seconds())
 
 //方式5 update
 start = time.Now()
 for i := 1401;i<=1500;i++{
 tx,_ := db.Begin()
 tx.Exec("UPdate user set age=? where uid=?",i,i)
 tx.Commit()
 }
 end = time.Now()
 fmt.Println("方式5 update total time:",end.Sub(start).Seconds())
 
}

func delete(){
 //方式1 delete
 start := time.Now()
 for i := 1001;i<=1100;i++{
 db.Exec("DELETE FROM USER WHERE uid=?",i)
 }
 end := time.Now()
 fmt.Println("方式1 delete total time:",end.Sub(start).Seconds())
 
 //方式2 delete
 start = time.Now()
 for i := 1101;i<=1200;i++{
 stm,_ := db.Prepare("DELETE FROM USER WHERE uid=?")
 stm.Exec(i)
 stm.Close()
 }
 end = time.Now()
 fmt.Println("方式2 delete total time:",end.Sub(start).Seconds())
 
 //方式3 delete
 start = time.Now()
 stm,_ := db.Prepare("DELETE FROM USER WHERE uid=?")
 for i := 1201;i<=1300;i++{
 stm.Exec(i)
 }
 stm.Close()
 end = time.Now()
 fmt.Println("方式3 delete total time:",end.Sub(start).Seconds())
 
 //方式4 delete
 start = time.Now()
 tx,_ := db.Begin()
 for i := 1301;i<=1400;i++{
 tx.Exec("DELETE FROM USER WHERE uid=?",i)
 }
 tx.Commit()
 
 end = time.Now()
 fmt.Println("方式4 delete total time:",end.Sub(start).Seconds())
 
 //方式5 delete
 start = time.Now()
 for i := 1401;i<=1500;i++{
 tx,_ := db.Begin()
 tx.Exec("DELETE FROM USER WHERE uid=?",i)
 tx.Commit()
 }
 end = time.Now()
 fmt.Println("方式5 delete total time:",end.Sub(start).Seconds())
 
}

func query(){
 
 //方式1 query
 start := time.Now()
 rows,_ := db.Query("SELECT uid,username FROM USER")
 defer rows.Close()
 for rows.Next(){
  var name string
  var id int
 if err := rows.Scan(&id,&name); err != nil {
  log.Fatal(err)
 }
 //fmt.Printf("name:%s ,id:is %d
", name, id)
 }
 end := time.Now()
 fmt.Println("方式1 query total time:",end.Sub(start).Seconds())
 
 //方式2 query
 start = time.Now()
 stm,_ := db.Prepare("SELECT uid,username FROM USER")
 defer stm.Close()
 rows,_ = stm.Query()
 defer rows.Close()
 for rows.Next(){
  var name string
  var id int
 if err := rows.Scan(&id,&name); err != nil {
  log.Fatal(err)
 }
 // fmt.Printf("name:%s ,id:is %d
", name, id)
 }
 end = time.Now()
 fmt.Println("方式2 query total time:",end.Sub(start).Seconds())
 
 
 //方式3 query
 start = time.Now()
 tx,_ := db.Begin()
 defer tx.Commit()
 rows,_ = tx.Query("SELECT uid,username FROM USER")
 defer rows.Close()
 for rows.Next(){
  var name string
  var id int
 if err := rows.Scan(&id,&name); err != nil {
  log.Fatal(err)
 }
 //fmt.Printf("name:%s ,id:is %d
", name, id)
 }
 end = time.Now()
 fmt.Println("方式3 query total time:",end.Sub(start).Seconds())
}

func insert() {
 
 //方式1 insert
 //strconv,int转string:strconv.Itoa(i)
 start := time.Now()
 for i := 1001;i<=1100;i++{
 //每次循环内部都会去连接池获取一个新的连接,效率低下
 db.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)
 }
 end := time.Now()
 fmt.Println("方式1 insert total time:",end.Sub(start).Seconds())
 
 //方式2 insert
 start = time.Now()
 for i := 1101;i<=1200;i++{
 //Prepare函数每次循环内部都会去连接池获取一个新的连接,效率低下
 stm,_ := db.Prepare("INSERT INTO user(uid,username,age) values(?,?,?)")
 stm.Exec(i,"user"+strconv.Itoa(i),i-1000)
 stm.Close()
 }
 end = time.Now()
 fmt.Println("方式2 insert total time:",end.Sub(start).Seconds())
 
 //方式3 insert
 start = time.Now()
 stm,_ := db.Prepare("INSERT INTO user(uid,username,age) values(?,?,?)")
 for i := 1201;i<=1300;i++{
 //Exec内部并没有去获取连接,为什么效率还是低呢?
 stm.Exec(i,"user"+strconv.Itoa(i),i-1000)
 }
 stm.Close()
 end = time.Now()
 fmt.Println("方式3 insert total time:",end.Sub(start).Seconds())
 
 //方式4 insert
 start = time.Now()
 //Begin函数内部会去获取连接
 tx,_ := db.Begin()
 for i := 1301;i<=1400;i++{
 //每次循环用的都是tx内部的连接,没有新建连接,效率高
 tx.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)
 }
 //最后释放tx内部的连接
 tx.Commit()
 
 end = time.Now()
 fmt.Println("方式4 insert total time:",end.Sub(start).Seconds())
 
 //方式5 insert
 start = time.Now()
 for i := 1401;i<=1500;i++{
 //Begin函数每次循环内部都会去连接池获取一个新的连接,效率低下
 tx,_ := db.Begin()
 tx.Exec("INSERT INTO user(uid,username,age) values(?,?,?)",i,"user"+strconv.Itoa(i),i-1000)
 //Commit执行后连接也释放了
 tx.Commit()
 }
 end = time.Now()
 fmt.Println("方式5 insert total time:",end.Sub(start).Seconds())
}

之前关于golang操作数据库的博客: 
Go实战–go语言操作sqlite数据库(The way to go)

Go实战–golang中使用MongoDB(mgo)

Go实战–golang中使用redis(redigo和go-redis/redis)

 

导入包

import (
"database/sql"
"fmt"

_ "github.com/go-sql-driver/mysql"
)
连接数据库

db, err := sql.Open("mysql", "root:wangshubo@/test?charset=utf8")
checkErr(err)
插入数据

stmt, err := db.Prepare("INSERT user_info SET id=?,name=?")
checkErr(err)

res, err := stmt.Exec(1, "wangshubo")
checkErr(err)
更新数据

stmt, err = db.Prepare("update user_info set name=? where id=?")
checkErr(err)

res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
查询

rows, err := db.Query("SELECT * FROM user_info")
checkErr(err)
删除

stmt, err = db.Prepare("delete from user_info where id=?")
checkErr(err)

res, err = stmt.Exec(id)
checkErr(err)

 

使用go语言数据库

标签:为什么   多个   存在   for   int   path   driver   follow   绝对路径   

热心网友 时间:2022-05-02 20:28

1、简单易学。

Go语言的作者本身就很懂C语言,所以同样Go语言也会有C语言的基因,所以对于程序员来说,Go语言天生就会让人很熟悉,容易上手。

2、并发性好。

Go语言天生支持并发,可以充分利用多核,轻松地使用并发。 这是Go语言最大的特点。

描述

Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。

在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。

热心网友 时间:2022-05-02 21:46

为什么要使用Go语言:

从工程的角度上来看,对于大多数后台应用场景,选择Golang是极为明智的选择。 这样可以很轻松的兼顾运行性能、开发效率及维护难度这三大让诸多程序猿欲仙欲死的奇点。

Go有什么优势:

可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。

静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高。

语言层面支持并发,这个就是Go最大的特色,天生的支持并发,我曾经说过一句话,天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发。

内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。

简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、重载、对象等。

丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,我最爱的也是这部分。

内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,想不一样都很困难。

跨平台编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用,如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息。

内嵌C支持,前面说了作者是C的作者,所以Go里面也可以直接包含c代码,利用现有的丰富的C库。

Go适合用来做什么:

服务器编程,以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。

分布式系统,数据库代理器等。

网络编程,这一块目前应用最广,包括Web应用、API应用、下载应用。

内存数据库,前一段时间google开发的groupcache,couchbase的部分组建。

云平台,目前国外很多云平台在采用Go开发,CloudFoundy的部分组建,前VMare的技术总监自己出来搞的apcera云平台。

热心网友 时间:2022-05-02 23:20

1、可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。
2、静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高。
3、语言层面支持并发,这个就是Go语言最大的特色,可以充分的利用多核,很容易的使用并发。
4、内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。
5、简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、重载、对象等。丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大。
6、内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,想不一样都很困难。跨平台编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用,如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息。
7、内嵌C语言支持,前面说了作者是C语言的作者,所以Go语言里面也可以直接包含C语言代码,利用现有的丰富的C语言库。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
苹果手机微信怎么换漂亮字体(苹果手机微信怎么换行输入) 有什么好用的app转换字体 手写转文字的软件 erp可以看评论地址吗 淘宝评论url是什么意思? 揭秘:码牌支付风控升级,背后真相揭秘 电脑电视直播软件哪个好用什么软件好电脑看电视直播 潼南子同街学区是哪些 三极管BU406价格和参数? 火锅料放在冰柜忘了插电一个星期给会坏了吗 火锅的设备有哪些 go语言支持开发桌面级应用吗?(求个编译器) golang的GUI包现在比较成熟的有哪些 go语言支持开发桌面级应用吗? golang为什么没有官方的gui包 华为mate20pro右下角,靠右边,有个隐形点赞图案,是怎么了? jabi 的微信怎么选择发送? jabi 的微信怎么选择发送? jabi扎比,你的微信应用闪退怎么回事 jabi微信封号怎么办 苹果用户怎样微信分身? 墨斗格斗游戏登录方式二维码 手机爱奇艺离线缓存在手机哪个文件夹 在爱奇艺里面下载的视频放在手机里 然后在文件管理... 手机爱奇艺缓存视屏在手机哪个文件夹里 爱奇艺储存文件在哪 苹果手机下载爱奇艺视频在哪个文件夹里? 华为mate40pro小圆点怎么设置 华为mate20pro左上角有一个圆圈里面是感叹号是什么意思 万能手电有哪些特点? 手摇手电好用吗? Go语言的优势有哪些 go语言是一种什么语言 go语言适合做什么? 为什么要使用 Go 语言,Go 语言的优势在哪里 为什么要使用 Go 语言?Go 语言的优势在哪里 GO语言是什么语言?我们应该怎么学? 《Go语言程序设计》epub下载在线阅读全文,求百度... 关于GO 语言的入门学习 求解答 Go 语言到底适合干什么? 微信如何查银行卡余额 微信如何查看银行卡余额 如何在微信里面查看银行卡里面有多少余额? 微信怎么查银行卡余额 微信查银行卡余额怎么查 微信怎么看银行卡余额还有多少 微信怎样查看银行卡余额? 微信银行卡怎么查余额 怎么查看微信帮定的银行卡余额? 微信怎么显示银行卡余额 怎么查微信绑定银行卡余额查询