If you have used nginx, you may know that nginx supports hot update, which means you can update your nginx without stopping and restarting it. It serves old connections with old version, and accepts new connections with new version. Notice that hot compiling is different from hot update, where hot compiling is monitoring your source files and recompile them when the content changes, it requires stop and restart your applications, `bee start` is a tool for hot compiling.
##Is hot update necessary?
## Is hot update necessary?
Some people says that hot update is not as useful as its cool name. In my opinion, this is absolutely necessary because zero-down server is our goal for our services. Even though sometimes some errors or hardware problems may occur, but it belongs to design of high availability, don't mix them up. Service update is a known issue, so we need to fix this problem.
##How Beego support hot update?
## How Beego support hot update?
The basic principle of hot update: main process fork a process, and child process execute corresponding programs. So what happens? We know that after forked a process, main process will have all handles, data and stack, etc, but all handles are saved in `CloseOnExec`, so all copied handles will be closed when you execute it unless you clarify this, and we need child process to reuse the handle of `net.Listener`. Once a process calls exec functions, it is "dead", system replaces it with new code. The only thing it left is the process ID, which is the same number but it is a new program after executed.
Therefore, the first thing we need to do is that let child process fork main process and through `os.StartProcess` to append files that contains handle that is going to be inherited.
...
...
@@ -15,7 +20,8 @@ The final step is that we want to serve old connections with old version of appl
Above are three problems that we need to solve, you can see my code logic for specific implementation.
##Show time
## Show time
1. Write code in your Get method:
...
...
@@ -29,7 +35,7 @@ Above are three problems that we need to solve, you can see my code logic for sp
One execute: ` ps -ef|grep <application name>`
Another one execute:`curl "http://127.0.0.1:8080/?sleep=20"`
Another one execute:`curl "http://127.0.0.1:8080/?sleep=20"`
Beego is a simple web framework, but it uses many third-party packages, so you have to install all dependency packages also.
- Before anything you do, you have to check that you installed Go in your computer, see more detail about Go installation in my book: [Chapter 1](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/01.1.md)
...
...
@@ -16,10 +17,10 @@ Good job, you're ready to Beego with powerful bee tools!
Hey, you say you've never heard about Beego and don't know how to use it? Don't worry, after you read this section, you will know a lot about Beego. Before you start reading, make sure you installed Beego in your computer, if not, check this tutorial: [Installation](Install.md)
**Navigation**
...
...
@@ -23,7 +24,9 @@ Hey, you say you've never heard about Beego and don't know how to use it? Don't
@@ -54,14 +57,21 @@ Open address [http://127.0.0.1:8080](http://127.0.0.1:8080) in your browser and
What happened in behind above example?
1. We import package `github.com/astaxie/beego`. As we know that Go initialize packages and runs init() function in every package(more detail [here](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/02.3.md#main-function-and-init-function)), so Beego initializes the BeeApp application at this time.
1. We import package `github.com/astaxie/beego`. As we know that Go initialize packages and runs init() function in every package ([more details](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/02.3.md#main-function-and-init-function)), so Beego initializes the BeeApp application at this time.
2. Define controller. We define a struct called `MainController` with a anonymous field `beego.Controller`, so the `MainController` has all methods that `beego.Controller` has.
3. Define RESTful methods. Once we use anonymous combination, `MainController` has already had `Get`, `Post`, `Delete`, `Put` and other methods, these methods will be called when user sends corresponding request, like `Post` method for requests that are using POST method. Therefore, after we overloaded `Get` method in `MainController`, all GET requests will use `Get` method in `MainController` instead of in `beego.Controller`.
4. Define main function. All applications in Go use main function as entry point as C does.
5. Register routers, it tells Beego which controller is responsibility for specific requests. Here we register `/` for `MainController`, so all requests in `/` will be handed to `MainController`. Be aware that the first argument is the path and the second one is pointer of controller that you want to register.
6. Run application in port 8080 as default, press `Ctrl+c` to exit.
## New project
Get into your $GOPATH, then use following command to setup Beego project:
bee create hello
...
...
@@ -82,7 +92,9 @@ It generates folders and files for your project, directory structure as follows:
└── views
└── index.tpl
## Development mode
Beego uses development mode as default, you can use following code to change mode in your application:
beego.RunMode = "pro"
...
...
@@ -104,7 +116,9 @@ In development mode, you have following effects:
![](images/dev.png)
## Router
The main function of router is to connect request URL and handler. Beego wrapped `Controller`, so it connects request URL and `ControllerInterface`. The `ControllerInterface` has following methods:
type ControllerInterface interface {
...
...
@@ -160,7 +174,9 @@ For more convenient configure route rules, Beego references the idea from sinatr
Match type string // match :hi is string type, Beego uses regular expression ([\w]+) automatically
##Static files
## Static files
Go provides `http.ServeFile` for static files, Beego wrapped this function and use following way to register static file folder:
After you setting static directory, when users visit `/images/login/login.png`,Beego accesses `images/login/login.png` in related to your application directory. One more example, if users visit `/static/img/logo.png`, Beego accesses file `public/img/logo.png`.
##Filter and middleware
## Filter and middleware
Beego supports customized filter and middleware, such as security verification, force redirect, etc.
Here is an example of verify user name of all requests, check if it's admin.
...
...
@@ -202,7 +220,9 @@ Filter by prefix is also available:
dosomething()
})
##Controller
## Controller
Use `beego.controller` as anonymous in your controller struct to implement the interface in Beego:
type xxxController struct {
...
...
@@ -266,7 +286,7 @@ Overload all methods for all customized logic processes, let's see an example:
}
func (this *AddController) Get() {
this.Data["content"] ="value"
this.Data["content"] ="value"
this.Layout = "admin/layout.html"
this.TplNames = "admin/add.tpl"
}
...
...
@@ -290,13 +310,19 @@ Overload all methods for all customized logic processes, let's see an example:
this.Ctx.Redirect(302, "/admin/index")
}
##Template
###Template directory
## Template
### Template directory
Beego uses `views` as the default directory for template files, parses and caches them as needed(cache is not enable in develop mode), but you can **change**(because only one directory can be used for template files) its directory using following code:
beego.ViewsPath = "/myviewpath"
###Auto-render
### Auto-render
You don't need to call render function manually, Beego calls it automatically after corresponding methods executed. If your application is somehow doesn't need templates, you can disable this feature either in code of `main.go` or configuration file.
To disable auto-render in configuration file:
...
...
@@ -307,13 +333,17 @@ To disable auto-render in `main.go`(before you call `beego.Run()` to run the app
beego.AutoRender = false
###Template data
### Template data
You can use `this.Data` in controller methods to access the data in templates. Suppose you want to get content of `{{.Content}}`, you can use following code to do this:
this.Data["Context"] = "value"
###Template name
Beego uses built-in template engine of Go, so there is no different in syntax. As for how to write template file, please visit [Template tutorial](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/07.4.md)。
### Template name
Beego uses built-in template engine of Go, so there is no different in syntax. As for how to write template file, please visit [Template tutorial](https://github.com/Unknwon/build-web-application-with-golang_EN/blob/master/eBook/07.4.md).
Beego parses template files in `viewpath` and render it after you set the name of the template file in controller methods. For example, Beego finds the file `add.tpl` in directory `admin` in following code:
...
...
@@ -329,7 +359,9 @@ If you enabled auto-render and you don't tell Beego which template file you are
Which is `<corresponding controller name>/<request method name>.<template extension>`. For example, your controller name is `AddController` and the request method is POST, and the default file extension is `tpl`, so Beego will try to find file `/<viewpath>/AddController/POST.tpl`.
###Layout design
### Layout design
Beego supports layout design, which means if you are working on an administration application, and some part of its user interface is exactly same all the time, then you can make this part as a layout.
this.Layout = "admin/layout.html"
...
...
@@ -347,7 +379,9 @@ Right now, Beego caches all template files, so you can use following way to impl
Handle logic
{{template "footer.html"}}
###Template function
### Template function
Beego supports customized template functions that are registered before you call `beego.Run()`.
func hello(in string)(out string){
...
...
@@ -366,32 +400,42 @@ There are some built-in template functions:
* markdown
This function converts markdown content to HTML format, use {{markdown .Content}} in template files.
* dateformat
This function converts time to formatted string, use {{dateformat .Time "2006-01-02T15:04:05Z07:00"}} in template files.
* date
This function implements date function like in PHP, use formatted string to get corresponding time, use {{date .T "Y-m-d H:i:s"}} in template files.
* compare
This functions compares two objects, returns true if they are same, false otherwise, use {{compare .A .B}} in template files.
* substr
This function cuts out string from another string by index, it supports UTF-8 characters, use {{substr .Str 0 30}} in template files.
* html2str
This function escapes HTML to raw string, use {{html2str .Htmlinfo}} in template files.
* str2html
This function outputs string in HTML format without escaping, use {{str2html .Strhtml}} in template files.
* htmlquote
This functions implements basic HTML escape, use {{htmlquote .quote}} in template files.
* htmlunquote
This functions implements basic invert-escape of HTML, use {{htmlunquote .unquote}} in template files.
##Handle request
## Handle request
We always need to get data from users, including methods like GET, POST, etc. Beego parses these data automatically, and you can access them by following code:
- GetString(key string) string
...
...
@@ -417,10 +461,12 @@ If you need other types that are not included above, like you need int64 instead
To use `this.Ctx.Request` for more information about request, and object properties and method please read [Request](http://golang.org/pkg/net/http/#Request)
###File upload
### File upload
It's very easy to upload file through Beego, but don't forget to add `enctype="multipart/form-data"` in your form, otherwise the browser will not upload anything.
Files will be saved in memory, if the size is greater than cache memory, the rest part will be saved as temporary file. The default cache memory is 64 MB, and you can using following ways to change this size.
Files will be saved in memory, if the size is greater than cache memory, the rest part will be saved as temporary file. The default cache memory is 64 MB, and you can use following ways to change this size.
In code:
...
...
@@ -446,7 +492,9 @@ This is an example to save file that is uploaded:
Beego considered API function design at the beginning, and we often use Json or XML format data as output. Therefore, it's no reason that Beego doesn't support it:
Set `content-type` to `application/json` for output raw Json format data:
...
...
@@ -465,7 +513,9 @@ Set `content-type` to `application/xml` for output raw XML format data:
this.ServeXml()
}
##Redirect and error
## Redirect and error
You can use following to redirect:
func (this *AddController) Get() {
...
...
@@ -493,15 +543,15 @@ Then Beego will not execute rest code of the function body when you call `this.A
Beego supports following error code: 404, 401, 403, 500 and 503, you can customize your error handle, for example, use following code to replace 404 error handle process:
func page_not_found(rw http.ResponseWriter, r *http.Request){
@@ -510,22 +560,24 @@ You may be able to use your own `404.html` for your 404 error.
Beego also gives you ability to modify error message that shows on the error page, the following example shows how to set more meaningful error message when database has problems:
func dbError(rw http.ResponseWriter, r *http.Request){
After you registered this customized error, you can use `this.Abort("dbError")` for any database error in your applications.
##Handle response
## Handle response
There are some situations that you may have in response:
1. Output template
...
...
@@ -542,7 +594,9 @@ There are some situations that you may have in response:
this.Ctx.WriteString("ok")
## Sessions
Beego has a built-in session module and supports four engines, including memory, file, MySQL and redis. You can implement your own engine based on the interface.
It's easy to use session in Beego, use following code in your main() function:
...
...
@@ -626,7 +680,9 @@ When the SessionProvider is redis, SessionSavePath is link address of redis, it
beego.SessionProvider = "redis"
beego.SessionSavePath = "127.0.0.1:6379"
## Cache
Beego has a built-in cache module, it's like memcache, which caches data in memory. Here is an example of using cache module in Beego:
var (
...
...
@@ -670,7 +726,9 @@ To use cache, you need to initialize a `beego.NewBeeCache` object and set expire
- Delete(name string) (ok bool, err error)
- IsExist(name string) bool
##Safe map
## Safe map
We know that map is not thread safe in Go, if you don't know it, this article may be helpful for you: [atomic_maps](http://golang.org/doc/faq#atomic_maps). However, we need a kind of thread safe map in practice, especially when we are using goroutines. Therefore, Beego provides a simple built-in thread safe map implementation.
bm := NewBeeMap()
...
...
@@ -697,7 +755,9 @@ This map has following interfaces:
- Check(k interface{}) bool
- Delete(k interface{})
##Log
## Log
Beego has a default BeeLogger object that outputs log into stdout, and you can use your own logger as well:
beego.SetLogger(*log.Logger)
...
...
@@ -712,7 +772,8 @@ You can output everything that implemented `*log.Logger`, for example, write to
lg := log.New(fd, "", log.Ldate|log.Ltime)
beego.SetLogger(lg)
###Different levels of log
### Different levels of log
* Trace(v ...interface{})
* Debug(v ...interface{})
...
...
@@ -731,36 +792,48 @@ Your project may have a lot of log outputs, but you don't want to output everyth
Then Beego will not output log that has lower level of LevelWarning. Here is the list of all log levels, order from lower to higher:
@@ -998,7 +1077,9 @@ Beego has an example for supporting chat of sockjs, here is the code:
The above example implemented a simple chat room for sockjs, and you can use `http.Handler` for more extensions.
##Deployment
## Deployment
Go compiles program to binary file, you only need to copy this binary to your server and run it. Because Beego uses MVC model, so you may have folders for static files, configuration files and template files, so you have to copy those files as well. Here is a real example for deployment.
Beego is a lightweight, open source, non-blocking and scalable web framework for the Go programming language. It's like tornado in Python. This web framework has already been using for building web server and tools in SNDA's CDN system. Documentation and downloads available at [http://astaxie.github.com/beego](http://astaxie.github.com/beego)
It has following main features:
...
...
@@ -19,7 +20,9 @@ The working principles of Beego as follows:
Beego is licensed under the Apache Licence, Version 2.0
People may ask me why I want to build a new web framework rather than use other good ones. I know there are many excellent web frameworks on the internet and almost all of them are open source, and I have my reasons to do this.
Remember when I was writing the book about how to build web applications with Go, I just wanted to tell people what were my valuable experiences with Go in web development, especially I have been working with PHP and Python for almost ten years. At first, I didn't realize that a small web framework can give great help to web developers when they are learning to build web applications in a new programming language, and it also helps people more by studying its source code. Finally, I decided to write a open source web framework called Beego as supporting materiel for my book.
...
...
@@ -9,7 +10,7 @@ I used to use CI in PHP and tornado in Python, there are both lightweight, so th
2. Learn more about languages by studying their source code, it's not hard to read and understand them because they are both lightweight frameworks.
3. It's quite easy to make secondary development of these frameworks for specific purposes.
Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in GO.
Those reasons are my original intention of implementing Beego, and used two chapters in my book to introduce and design this lightweight web framework in Go.
Then I started to design logic execution of Beego. Because Go and Python have somewhat similar, I referenced some ideas from tornado to design Beego. As you can see, there is no different between Beego and tornado in RESTful processing; they both use GET, POST or some other methods to implement RESTful. I took some ideas from [https://github.com/drone/routes](https://github.com/drone/routes) at the beginning of designing routes. It uses regular expression in route rules processing, which is an excellent idea that to make up for the default Mux router function in Go. However, I have to design my own interface in order to implement RESTful and use inherited ideas in Python.