golang web 开发 go语言语法 包结构 注意事项 web开发案例 postgres数据库连接 增删改查案例

golang web 开发入门 go语言语法 注意事项 web开发案例 postgres数据库连接 增删改查案例

安装go语言

**打开官网https://golang.google.cn/dl/

下载好一键式安装**
go语言编辑工具VSCod
附一个链接: https://pan.baidu.com/s/1JAXnBgjL-sgh-IaxHcAG0g
提取码: 22sq

go语言和java不同的地方

定义的常量、变量、结构、函数等的名称是大写字母开头表示能被其它包访问或调用(相当于public),非大写开头就只能在包内使用(相当于private,变量或常量也可以下划线开头)
go语言还有一个特点每句代码结尾不需要用分号结尾

变量声明:

var(
 	a,b,c int
	c,d,e string

与其他语言不通的是 先声明变量后声明变量类型

如果输入参数必须指定类型;如果一个输入参数找不到类型,就会往后找:

a,b int,c string ,a,b,c int//对:
a,b int,c ; //错:
//或者
var (
a,b int
c,d string
)

函数定义


func function_name( a int,b int )(string,string) 
{
	return string string
}

需要注意的是和Java不同返回值在参数列表小括号后面还可以再加上一个小括号逗号隔开返回多个参数 ,返回的时候在return 后面以空格隔开.如果需要对方法参数进行修改还需要在传进来的参数前加上*号(指针)
例如

func func_name(student *Student) Student {
 	 student.Name ="老王"
return student 
}

结构体

例如:

type Student struct {
     Name string
     Age int
     }

类似于Java里的mod 可以用来当作实体类使用

切片

//初始化一个切片
arr := []int
//常用的追加内容方法
 arr= append(arr,0,2,3)

切片不需要说明长度,go语言没有list ,切片相当于arraylist底层的动态数组,需要注意的地方是追加内容时需要用原切片接受一次否则追加内容不成功 也类似于java的动态数组 追加内容产生的 新数组 再把新数组赋值给原数组

Map(集合)

//创建一个map

 map1:= make(map[int]string) 
//追加内容
map1[0]="你好呀"
map1[1]="这个美丽的世界"

//查找内容
    name, ok := map1 [0]
     /*如果确定是真实的,则存在,否则不存在 */
    if (ok) {
        fmt.Println("key0的values是", name)
    } else {
        fmt.Println("key0是不存在的")
    }

map需要注意的是map名称不可以定义成“map"
因为map在go语言属于关键字调用的时候可能会报错

range(循环)

//示例1
for i:=0;i<10;i++{
	fmt.println("%s -> %s\n","循环次数",i)
}
//死循环
for{
}

go语言中相比于java中没有while循环使用range更加简洁

range还有一种写法类似于java中的增强for循环
示例:

//创建一个map并赋值
map1 := make(map[int]string)
map[0]="你"
map[1]="好"
map[2]="呀"

for k,v:= range map1{
	//打印的是key的值
	fmt.println(k)
	//打印的是value的值
	fmt.println(v)
}

//遍历数组

arr = :[]string
arr = append(arr,"你")
arr = append(arr,"好")
arr = append(arr,"呀")

for i,v:= range arr{
//打印的是次数
fmt.println(i)
//打印的是值
fmt.println(v)
}

//如果上面这个i索引不需要也可以在定义的时候用_替代省略掉
//如下
for _,v:=range arr{
}

goweb(http/template)

先上一段代码


package main
//需要引入的包
import (
	"fmt"
	"html/template"
	"net/http"
)

// 定义一个结构体
type Person struct {
	Name    string
	Imageid int
}
// 第一个请求页面
func Hello(w http.ResponseWriter, r *http.Request) {
	var arr []Person
	p := Person{Imageid: 1, Name: "我的个人网站"}
	p1 := Person{Imageid: 2, Name: "我的个人网站1"}
	p2 := Person{Imageid: 3, Name: "我的个人网站2"}
	p3 := Person{Imageid: 4, Name: "我的个人网站"}
	arr = append(arr, p)
	arr = append(arr, p1)
	arr = append(arr, p2)
	arr = append(arr, p3)
	//这里是引入web页面的的html相对地址
	tmpl, err := template.ParseFiles("view/index.html")
	if err != nil {
		fmt.Println("parse file err:", err)
	}

	fmt.Println("handle hello")
	// fmt.Fprintf(w, "hello ")

	tmpl.Execute(w, arr)
}


func main() {

	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	http.HandleFunc("/product", Hello)
	//不同的页面书写不同的handlerFunc就可以了
	//http.HandleFunc("/product/more", more)
	//http.HandleFunc("/solution", solution)
	err := http.ListenAndServe("0.0.0.0:8080", nil)
	if err != nil {
		fmt.Println("http listen failed")
	}

}

其中可能很多初学者都会遇到的问题就是前端页面模板调用之后样式都会消失了
解决办法就是下面这一段

http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

这段代码是引入静态资源的相对位置
同时web页面模板调用静态资源的的时候也要遵循一定的规则web代码如下:

<link rel="stylesheet" type="text/css" href="/static/layui/css/layui.css">
  <script type="text/javascript" src="/static/layui/layui.js"></script>

样式不乱了之后我们可以把后端的内容便利到页面上去,关键代码如下

				{{range .}}
                {{if eq .Imageid 1}}
                 <a href="/product/more"> <img src="/static/img/1.jpg" alt=""></a>
                    {{else}}
                    <img src="/static/img/{{.Imageid}}.jpg" alt="">
                    {{end}}
                    <p class="data">{{.Name}}</p>
                {{end}}

web开发的时候还有一点就是要注意包的结构
示例结构如下:
go模板结构
其中不介意模板和静态资源放在一起是因为在go中设置了静态路径之后如果网页也在静态资源之下就会导致模板文件暴露可以被直接访问到

其中模板语法我们可以参照go语言标准库http/template例如一下一些常用写法
判断
golang的模板也支持if的条件判断,当前支持最简单的bool类型和字符串类型的判断

{{if .condition}}
{{end}}
当.condition为bool类型的时候,则为true表示执行,当.condition为string类型的时候,则非空表示执行。

当然也支持else , else if嵌套

{{if .condition1}}
{{else if .contition2}}
{{end}}
假设我们需要逻辑判断,比如与或、大小不等于等判断的时候,我们需要一些内置的模板函数来做这些工作,目前常用的一些内置模板函数有:

not 非

{{if not .condition}}
{{end}}

and 与

{{if and .condition1 .condition2}}
{{end}}

or 或

{{if or .condition1 .condition2}}
{{end}}

eq 等于

{{if eq .var1 .var2}}
{{end}}

ne 不等于

{{if ne .var1 .var2}}
{{end}}

lt 小于 (less than)

{{if lt .var1 .var2}}
{{end}}

le 小于等于

{{if le .var1 .var2}}
{{end}}

gt 大于

{{if gt .var1 .var2}}
{{end}}

ge 大于等于

{{if ge .var1 .var2}}
{{end}}

循环
golang的template支持range循环来遍历map、slice内的内容,语法为:

{{range i,v := .slice}}
{{end}}
在这个range循环内,我们可以通过iv来访问遍历的值,还有一种遍历方式为:

{{range .slice}}
{{end}}
这种方式无法访问到index或者key的值,需要通过.来访问对应的value

{{range .slice}}
{{.field}}
{{end}}

go+postgres

**首先需要安装好postgres 数据库
附一个下载链接http://postgres.cn/v2/download
**

安装好了先上一段代码


package psql

import (
	"database/sql"
	"fmt"
	"log"
	"time"

	// postgres
	_ "github.com/lib/pq"
)

const (
	host     = "localhost"
	port     = 5432
	user     = "postgres"
	password = "123"
	dbname   = "test"
)

func init() {
	InitDB()
}

//
type Test struct {
	ID   int
	Name string
	// time.Time  timestamptz
	// jsonb
}
//定义一个常量连接池
var (
	GDB *sql.DB
)
//初始化连接池
/.这里利用的类似于java中的单利模式饿汉模式先创建好连接池持续调用同一个对象./
func InitDB() {
	GDB = ConnectDB()
}
func ConnectDB() *sql.DB {
	psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
		"password=%s dbname=%s sslmode=disable",
		host, port, user, password, dbname)
	//第一个参数是对应的数据库驱动名称
	db, err := sql.Open("postgres", psqlInfo)
	if err != nil {
		panic(err)
	}
	//测试数据库能否连接成功
	err = db.Ping()
	if err != nil {
		panic(err)
	}
	fmt.Println("Successfully connected")
	return db
}

好了如果到这里都没有问题就可以进行我们的增删改查操作了我们先创建一个表利用pqAdmin手动创建数据库和一个表
表结构如下:
测试表的表结构
增加方法:

const (
	sqlInsert = "insert into test (name)values($1) returning id"
)

//
func Insert() {
	_, err := GDB.Exec(sqlInsert, "张三")
	if err != nil {
		log.Fatal(err)
	} else {
		fmt.Println("insert into test success")
	}
}

删除方法:

const (
	sqldelete = "delete from test where name = $1"
)

//
func delete() {
	_, err := GDB.Exec(sqldelete, "张三")
	if err != nil {
		log.Fatal(err)
	} else {
		fmt.Println("delete test success")
	}
}

修改方法:

func Update() {
	stmt, err := GDB.Prepare("update test set name= $1 where id = $2")
	if err != nil {
		log.Fatal(err)
	}
	_, err = stmt.Exec("李四", 2)
	if err != nil {
		log.Fatal(err)
	} else {
		fmt.Println("update test success")
	}
}

查询方法:

//先创建一个和表结构一样的结构体用来接收表数据
type Test struct {
	ID   int
	Name string
}

//查询单行代码
/.查询单个数据介意使用queryRow方法./
func QueryRow() {
	var test1 Test
	sql := "select * from test where id=$1"
	err := GDB.QueryRow(sql, 1).Scan(&test1.Name, &test1.ID)
	if err != nil {
		log.Fatal(err)
	}
	//打印出查出来的对象
	fmt.Println(test1)
}

//查询多条数据
func Query() []Test {
	var (
		tests []Test
		test1 Test
	)
	//这里查出来的是很多条数据我们可以定义一个切片来存储
	rows, err := GDB.Query("select * from test")
	if err != nil {
		fmt.Println(err)
	}

	defer rows.Close()
	//多条数据的语句需要使用for循环遍历出来
	for rows.Next() {
		err := rows.Scan(&test1.Name, &test1.ID)
		if err != nil {
			fmt.Println(err)
			break
		} else {
			fmt.Print("刚才添加的数据是:")
			fmt.Println(test1)
			tests = append(tests, test1)
		}
	}

	fmt.Println()
	return tests
}

然后我们就可以愉快的运行了

func main (){
	//这里查出来的是一个切片我们可以打印出来看看
	fmt.println(Query())
	QueryRow()
	Insert()
	delete()
	Update()
}

一起学习—持续更新-------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值