Simple Go server framework inspired by Express
Pine is built on the same concepts of ease of use such as Fiber golang or Express JS.
If you are familiar with Express or Fiber, Pine will be a breeze to use.
Build Faster, Understand Deeper
Pine is built on the same concepts of ease of use such as Fiber golang or Express JS.
If you are familiar with Express or Fiber, Pine will be a breeze to use.
package main
import (
"log"
"github.com/BryanMwangi/pine"
)
func main() {
app := pine.New()
app.Get("/hello", func(c *pine.Ctx) error {
return c.SendString("Hello World!")
})
log.Fatal(app.Start(":3000", "", ""))
}
There are a tonne of frameworks out there and often than not, they do not differ from each other. Pine is no different. However, what Pine wants to offer is not just a tool or a framework, but a place to learn how frameworks are actually built.
Understand how frameworks work and as you advance as a developer learn how to implement some of the solutions yourself. You can check out deep dive examples in our advanced documentation.
package main
import (
"log"
"net/http"
"github.com/BryanMwangi/pine"
)
// example for a struct
type MyParams struct {
Name string
Age int
}
func main() {
app := pine.New()
// bind params
app.Get("/hello/:name", func(c *pine.Ctx) error {
params := new(MyParams)
err := c.BindParam("name", ¶ms.Name)
if err != nil {
return c.SendStatus(http.StatusBadRequest)
}
return c.SendString("Hello " + params.Name)
})
log.Fatal(app.Start(":3000", "", ""))
}
Under the hood
var (
ErrParse = errors.New("bind: cannot parse")
ErrConvert = errors.New("bind: cannot convert")
ErrType = errors.New("bind: unexpected type")
ErrPtr = errors.New("bind: destination must be a pointer")
ErrValidation = errors.New("bind: validation failed")
)
func (c *Ctx) BindParam(key string, v interface{}) error {
param := c.Params(key)
if param == "" {
return ErrValidation
}
return bind(param, v)
}
// Internal helper function to validate the bind
// requires the input in this case is the key of the param or query
// and the destination is the value of the param or query
func bind(input string, destination interface{}) error {
// reflect the type and value of the destination
typ := reflect.TypeOf(destination)
val := reflect.ValueOf(destination)
// Check if the destination is a pointer
if typ.Kind() != reflect.Ptr {
return ErrPtr
}
// Dereference pointer type to assign value
val = reflect.Indirect(val)
switch val.Kind() {
case reflect.String:
val.SetString(input)
case reflect.Int, reflect.Int64:
parsed, err := strconv.ParseInt(input, 10, 64)
if err != nil {
return ErrConvert
}
val.SetInt(parsed)
case reflect.Float64, reflect.Float32:
parsed, err := strconv.ParseFloat(input, 64)
if err != nil {
return ErrConvert
}
val.SetFloat(parsed)
case reflect.Bool:
parsed, err := strconv.ParseBool(input)
if err != nil {
return ErrConvert
}
val.SetBool(parsed)
default:
return ErrType
}
return nil
}
Pine offers exceptional performance compared to other frameworks. Currently Pine aims to compete with Express JS and Fiber. Pine is able to keep up or sometimes beat Fiber in synthetic tests. Benchmarks were carried out using Oha
Pine prides itself on simplicity. The core principles of Pine are simplicity and performance.
With Pine you are able to inspect and provide improvements to what runs Pine. Check out the advcanced documentation
directory to see how Pine works.
Easily one of the most readable and performant languages available and Pine takes full advantage of Go's speed and simplicity.