标签:exist 列表 forbidden 种类 serer usb 单词 occurred filename
2019年12月16日16:57:04
2019年11月01日15:56:09
Go 语言的接口设计是非侵入式的,接口编写者无须知道接口被哪些类型实现。
而接口实现者只需知道实现的是什么样子的接口,但无须指明实现哪一个接口。
编译器知道最终编译时使用哪个类型实现哪个接口,或者接口应该由谁来实现。
每个接口类型由数个方法组成。接口的形式代码如下:
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
对各个部分的说明:
type writer interface{
Write([]byte) error
}
判断r的真实类型,是不是mock.Retriever类型实现的。
r.(*mock.Retriever)
r.(type)
// Type assertion
if mockRetriever, ok := r.(*mock.Retriever); ok {
fmt.Println(mockRetriever.Contents)
} else {
fmt.Println("r is not a mock retriever")
}
fmt.Println(
"Try a session with mockRetriever")
fmt.Println(session(&mockRetriever))
}
fmt.println("%T %v ",r,r)
func inspect(r Retriever) {
fmt.Println("Inspecting", r)
fmt.Printf(" > Type:%T Value:%v\n", r, r)
fmt.Print(" > Type switch: ")
switch v := r.(type) {
case *mock.Retriever:
fmt.Println("Contents:", v.Contents)
case *real.Retriever:
fmt.Println("UserAgent:", v.UserAgent)
}
fmt.Println()
}
var r Retriever
mockRetriever := mock.Retriever{
Contents: "this is a fake imooc.com"}
r = &mockRetriever
inspect(r)
r = &real.Retriever{
UserAgent: "Mozilla/5.0",
TimeOut: time.Minute,
}
interface{}
支持任何类型
type Queue []interface{}
func (q *Queue) Push(v interface{}) {
*q=append(*q,v)
}
Type Assertion
Type Switch
2019年11月03日
2019年11月03日13:33:08
type Poster interface {
Post(url string,
form map[string]string) string
}
func post(poster Poster) {
poster.Post(url,
map[string]string{
"name": "ccmouse",
"course": "golang",
})
}
type RetrieverPoster interface {
Retriever
Poster
}
//mockretriever.go
func (r *Retriever) Post(url string,
form map[string]string) string {
r.Contents = form["contents"]
return "ok"
}
//main.go
func session(s RetrieverPoster) string {
s.Post(url, map[string]string{
"contents": "another faked imooc.com",
})
return s.Get(url)
}
func main() {
var r Retriever
mockRetriever := mock.Retriever{
Contents: "this is a fake imooc.com"}
r = &mockRetriever
inspect(r)
r = &real.Retriever{
UserAgent: "Mozilla/5.0",
TimeOut: time.Minute,
}
inspect(r)
fmt.Println(
"Try a session with mockRetriever")
fmt.Println(session(&mockRetriever))
}
2019年11月03日14:53:11
#### 2.闭包
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8kwses02tj313u0u0h1k.jpg" alt="image-20191103150946598" style="zoom:25%;" />
#### 3.匿名函数
Go语言支持匿名函数,即在需要使用函数时再定义函数,匿名函数没有函数名只有函数体,函数可以作为一种类型被赋值给函数类型的变量,匿名函数也往往以变量方式传递,这与C语言的回调函数比较类似,不同的是,Go语言支持随时在代码里定义匿名函数。
**定义一个匿名函数**
匿名函数的定义格式如下:
func(参数列表)(返回参数列表){
函数体
}
```
匿名函数的定义就是没有名字的普通函数定义。
在定义时调用匿名函数
匿名函数可以在声明后调用,例如:
func(data int) {
fmt.Println(
"hello", data)
}(100)
注意第3行} (100)
将匿名函数赋值给变量
匿名函数可以被赋值,例如:
// 将匿名函数体保存到f()中
f := func(data int) {
fmt.Println("hello", data)
}
// 使用f()调用
f(100)
匿名函数的用途非常广泛,它本身就是一种值,可以方便地保存在各种容器中实现回调函数和操作封装。
被捕获到闭包中的变量让闭包本身拥有了记忆效应,闭包中的逻辑可以修改闭包捕获的变量,变量会跟随闭包生命期一直存在,闭包本身就如同变量一样拥有了记忆效应。
累加器的实现:
package main
import (
"fmt"
)
// 提供一个值, 每次调用函数会指定对值进行累加
func Accumulate(value int) func() int {
// 返回一个闭包
return func() int {
// 累加
value++
// 返回一个累加值
return value
}
}
func main() {
// 创建一个累加器, 初始值为1
accumulator := Accumulate(1)
// 累加1并打印
fmt.Println(accumulator())
fmt.Println(accumulator())
// 打印累加器的函数地址
fmt.Printf("%p\n", accumulator)
// 创建一个累加器, 初始值为1
accumulator2 := Accumulate(10)
// 累加1并打印
fmt.Println(accumulator2())
// 打印累加器的函数地址
fmt.Printf("%p\n", accumulator2)
}
代码说明如下:
对比输出的日志发现 accumulator 与 accumulator2 输出的函数地址不同,因此它们是两个不同的闭包实例。
2019年11月03日16:00:50
Open/Close
Lock/unlock
PrintHeader/PrintFooter
package main
import (
"fmt"
"os"
"u2pppw/src/functional/fib"
"bufio"
)
func tryDefer() {
for i := 0; i < 100; i++ {
defer fmt.Println(i)
if i == 30 {
// Uncomment panic to see
// how it works with defer
// panic("printed too many")
}
}
}
func writeFile(filename string) {
file, err := os.OpenFile(filename,
os.O_EXCL|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
if pathError, ok := err.(*os.PathError); !ok {
panic(err)
} else {
fmt.Printf("%s, %s, %s\n",
pathError.Op,
pathError.Path,
pathError.Err)
}
return
}
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush()
f := fib.Fibonacci()
for i := 0; i < 20; i++ {
fmt.Fprintln(writer, f())
}
}
func main() {
tryDefer()
writeFile("fib.txt")
}
2019年11月03日16:57:12
if err != nil {
if pathError, ok := err.(*os.PathError); !ok {
panic(err)
} else {
fmt.Printf("%s, %s, %s\n",
pathError.Op,
pathError.Path,
pathError.Err)
}
return
}
读取方法
const prefix = "/list/"
func HandleFileList(writer http.ResponseWriter,
request *http.Request) error {
fmt.Println()
if strings.Index(
request.URL.Path, prefix) != 0 {
return userError(
fmt.Sprintf("path %s must start "+
"with %s",
request.URL.Path, prefix))
}
path := request.URL.Path[len(prefix):]
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
all, err := ioutil.ReadAll(file)
if err != nil {
return err
}
writer.Write(all)
return nil
}
处理错误的包装方法——使用函数式编程
type appHandler func(writer http.ResponseWriter,
request *http.Request) error
func errWrapper(
handler appHandler) func(
http.ResponseWriter, *http.Request) {
return func(writer http.ResponseWriter,
request *http.Request) {
// panic
defer func() {
if r := recover(); r != nil {
log.Printf("Panic: %v", r)
http.Error(writer,
http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
}
}()
err := handler(writer, request)
if err != nil {
log.Printf("Error occurred "+
"handling request: %s",
err.Error())
// user error
if userErr, ok := err.(userError); ok {
http.Error(writer,
userErr.Message(),
http.StatusBadRequest)
return
}
// system error
code := http.StatusOK
switch {
case os.IsNotExist(err):
code = http.StatusNotFound
case os.IsPermission(err):
code = http.StatusForbidden
default:
code = http.StatusInternalServerError
}
http.Error(writer,
http.StatusText(code), code)
}
}
}
main方法
func main() {
http.HandleFunc("/",
errWrapper(filelisting.HandleFileList))
err := http.ListenAndServe(":8888", nil)
if err != nil {
panic(err)
}
}
main.go
package main
import (
"log"
"net/http"
_ "net/http/pprof"
"os"
"u2pppw/src/errhandling/filelistingserver/filelisting"
)
type appHandler func(writer http.ResponseWriter,
request *http.Request) error
func errWrapper(
handler appHandler) func(
http.ResponseWriter, *http.Request) {
return func(writer http.ResponseWriter,
request *http.Request) {
// panic
defer func() {
if r := recover(); r != nil {
log.Printf("Panic: %v", r)
http.Error(writer,
http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
}
}()
err := handler(writer, request)
if err != nil {
log.Printf("Error occurred "+
"handling request: %s",
err.Error())
// user error
if userErr, ok := err.(userError); ok {
http.Error(writer,
userErr.Message(),
http.StatusBadRequest)
return
}
// system error
code := http.StatusOK
switch {
case os.IsNotExist(err):
code = http.StatusNotFound
case os.IsPermission(err):
code = http.StatusForbidden
default:
code = http.StatusInternalServerError
}
http.Error(writer,
http.StatusText(code), code)
}
}
}
type userError interface {
error
Message() string
}
func main() {
http.HandleFunc("/",
errWrapper(filelisting.HandleFileList))
err := http.ListenAndServe(":8888", nil)
if err != nil {
panic(err)
}
}
handle.go
package filelisting
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
)
const prefix = "/list/"
type userError string
func (e userError) Error() string {
return e.Message()
}
func (e userError) Message() string {
return string(e)
}
func HandleFileList(writer http.ResponseWriter,
request *http.Request) error {
fmt.Println()
if strings.Index(
request.URL.Path, prefix) != 0 {
return userError(
fmt.Sprintf("path %s must start "+
"with %s",
request.URL.Path, prefix))
}
path := request.URL.Path[len(prefix):]
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
all, err := ioutil.ReadAll(file)
if err != nil {
return err
}
writer.Write(all)
return nil
}
2019年11月04日14:00:22
defer func() {
err:=recover()
}()
package main
import (
"fmt"
)
func tryRecover() {
defer func() {
r := recover()
if r == nil {
fmt.Println("Nothing to recover. " +
"Please try uncomment errors " +
"below.")
return
}
if err, ok := r.(error); ok {
fmt.Println("Error occurred:", err)
} else {
panic(fmt.Sprintf(
"I don't know what to do: %v", r))
}
}()
// Uncomment each block to see different panic
// scenarios.
// Normal error
//panic(errors.New("this is an error"))
// Division by zero
//b := 0
//a := 5 / b
//fmt.Println(a)
// Causes re-panic
panic(123)
}
func main() {
tryRecover()
}
2019年11月04日14:49:18
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 1000; i++ {
go func(i int) {
for {
fmt.Printf("Hello from "+
"goroutine %d\n", i)
}
}(i)
}
time.Sleep(time.Minute)
}
轻量级线程
非抢占式多任务处理,由协程主动交出控制权
多个协程可能在一个或多个线程上运行
func main() {
var a [10]int
for i:=0;i<10;i++{
go func(i int){
for{
//fmt.Println("hello %d\n",i)
a[i]++
runtime.Gosched()
}
}(i)
}
time.Sleep(time.Millisecond)
fmt.Println(a)
}
I/O,select
channel
等待锁
函数调用
runtime,Gosched()
2019年11月04日15:30:28
Go语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。goroutine 间通过通道就可以通信。
通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。
通道本身需要一个类型进行修饰,就像切片类型需要标识元素类型。通道的元素类型就是在其内部传输的数据类型,声明如下:
var 通道变量 chan 通道类型
chan 类型的空值是 nil,声明后需要配合 make 后才能使用。
通道是引用类型,需要使用 make 进行创建,格式如下:
通道实例 := make(chan 数据类型)
请看下面的例子:
ch1 := make(chan int) // 创建一个整型类型的通道
ch2 := make(chan interface{}) // 创建一个空接口类型的通道, 可以存放任意格式
type Equip struct{ /* 一些字段 */ }
ch2 := make(chan *Equip) // 创建Equip指针类型的通道, 可以存放*Equip
// 创建一个空接口通道
ch := make(chan interface{})
// 将0放入通道中
ch <- 0
// 将hello字符串放入通道中
ch <- "hello"
2019年12月06日13:28:50
beego有八个模块,分别是
beego是一个类似tornado的Go应用框架,采用了RESTFul的方式来实现应用框架,是一个超轻量级的框架,主要有如下的特点:
beego 的安装是典型的 Go 安装包的形式:
go get github.com/astaxie/beego
Go 升级,通过该方式用户可以升级 beego 框架,强烈推荐该方式:
go get -u github.com/astaxie/beego
源码下载升级,用户访问 https://github.com/astaxie/beego
,下载源码,然后覆盖到 $GOPATH/src/github.com/astaxie/beego
目录,然后通过本地执行安装就可以升级了:
go install github.com/astaxie/beego
bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署。
您可以通过如下的方式安装 bee 工具:
go get github.com/beego/bee
安装完之后,bee
可执行文件默认存放在 $GOPATH/bin
里面,所以您需要把 $GOPATH/bin
添加到您的环境变量中,才可以进行下一步。
new
命令new
命令是新建一个 Web 项目,我们在命令行下执行 bee new <项目名>
就可以创建一个新的项目。但是注意该命令必须在 $GOPATH/src
下执行。最后会在 $GOPATH/src
相应目录下生成如下目录结构的项目:
bee new myproject
[INFO] Creating application...
/gopath/src/myproject/
/gopath/src/myproject/conf/
/gopath/src/myproject/controllers/
/gopath/src/myproject/models/
/gopath/src/myproject/static/
/gopath/src/myproject/static/js/
/gopath/src/myproject/static/css/
/gopath/src/myproject/static/img/
/gopath/src/myproject/views/
/gopath/src/myproject/conf/app.conf
/gopath/src/myproject/controllers/default.go
/gopath/src/myproject/views/index.tpl
/gopath/src/myproject/main.go
13-11-25 09:50:39 [SUCC] New application successfully created!
myproject
├── conf
│ └── app.conf
├── controllers
│ └── default.go
├── main.go
├── models
├── routers
│ └── router.go
├── static
│ ├── css
│ ├── img
│ └── js
├── tests
│ └── default_test.go
└── views
└── index.tpl
8 directories, 4 files
api
命令上面的 new
命令是用来新建 Web 项目,不过很多用户使用 beego 来开发 API 应用。所以这个 api
命令就是用来创建 API 应用的,执行命令之后如下所示:
bee api apiproject
create app folder: /gopath/src/apiproject
create conf: /gopath/src/apiproject/conf
create controllers: /gopath/src/apiproject/controllers
create models: /gopath/src/apiproject/models
create tests: /gopath/src/apiproject/tests
create conf app.conf: /gopath/src/apiproject/conf/app.conf
create controllers default.go: /gopath/src/apiproject/controllers/default.go
create tests default.go: /gopath/src/apiproject/tests/default_test.go
create models object.go: /gopath/src/apiproject/models/object.go
create main.go: /gopath/src/apiproject/main.go
这个项目的目录结构如下:
apiproject
├── conf
│ └── app.conf
├── controllers
│ └── object.go
│ └── user.go
├── docs
│ └── doc.go
├── main.go
├── models
│ └── object.go
│ └── user.go
├── routers
│ └── router.go
└── tests
└── default_test.go
从上面的目录我们可以看到和 Web 项目相比,少了 static 和 views 目录,多了一个 test 模块,用来做单元测试的。
同时,该命令还支持一些自定义参数自动连接数据库创建相关 model 和 controller:
bee api [appname] [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
如果 conn 参数为空则创建一个示例项目,否则将基于链接信息链接数据库创建项目。
run
命令我们在开发 Go 项目的时候最大的问题是经常需要自己手动去编译再运行,bee run
命令是监控 beego 的项目,通过 fsnotify监控文件系统。但是注意该命令必须在 $GOPATH/src/appname
下执行。
这样我们在开发过程中就可以实时的看到项目修改之后的效果:
bee run
13-11-25 09:53:04 [INFO] Uses 'myproject' as 'appname'
13-11-25 09:53:04 [INFO] Initializing watcher...
13-11-25 09:53:04 [TRAC] Directory(/gopath/src/myproject/controllers)
13-11-25 09:53:04 [TRAC] Directory(/gopath/src/myproject/models)
13-11-25 09:53:04 [TRAC] Directory(/gopath/src/myproject)
13-11-25 09:53:04 [INFO] Start building...
13-11-25 09:53:16 [SUCC] Build was successful
13-11-25 09:53:16 [INFO] Restarting myproject ...
13-11-25 09:53:16 [INFO] ./myproject is running...
我们打开浏览器就可以看到效果 http://localhost:8080/
标签:exist 列表 forbidden 种类 serer usb 单词 occurred filename
原文地址:https://www.cnblogs.com/oneapple/p/12050549.html