Go! Map Server

Today

  • Let it Go
  • GIS Server with Go
  • Talk is cheap, Let me show you the code

I am

  • Engineer @Samsung SDS
  •       @iam_keen
  • github.com/ehrudxo 

I did

  • Write a Node GIS Server code
  • Participate in QGIS menu Korean translation

Let it Go

https://golang.org/

Go is Good

  • Concurrency
  • It has compiler!
  • Cross-Compiler!
  • Light-weight
  • Various Tools (Python?)
  • Rapid Dev
  • Easy To Use
  • Functional Programming
  • ....

Go Spec

Go is a general-purpose language designed with systems programming in mind. It is strongly typed and garbage-collected and has explicit support for concurrent programming. Programs are constructed from packages, whose properties allow efficient management of dependencies. The existing implementations use a traditional compile/link model to generate executable binaries

Feature

  • Strongly Typed

  • Garbage Collected

  • Concurrent Programming

  • Package

  • No class, but structs​

  • Executable Binaries

http://golang.org/ref/spec

Strongly Typed

package main
import "fmt"

func main(){
  hiString  := "Hello "
  objString := "World"
  fmt.Println(hiString + objString +1)
}
# command-line-arguments
.\Test.go:7: cannot convert 4 to type string
.\Test.go:7: invalid operation: (hiString + objString) + 4 (mismatched types string and int)
package main
import (
  "fmt"
  "strconv"
)

func main(){
  hiString  := "Hello "
  objString := "World"
  fmt.Println(hiString + objString +strconv.Itoa(1))
}

Garbage Collection

Executable File

GC

Go

Virtual Machint

GC

Java, C#, Ruby, Python

Concurrent Programming

Go's concurrency primitives make it easy to construct streaming data pipelines that make efficient use of I/O and multiple CPUs.

- The Go Blog

package main
 
import "fmt"
 
func f(n int) {
    for i := 0; i < 10; i++ {
        fmt.Println(n, ":", i)
    }
}
 
func main() {
    go f(0)
    var input string
    fmt.Scanln(&input)
}

Package

package main
 
import "fmt"
import "github.com/ehrudxo/mApi/math"
 
func main() {
    xs := []float64{1,2,3,4}
    avg := math.Average(xs)
    fmt.Println(avg)
}
import m "github.com/ehrudxo/mApi/math"
 
func main() {
    xs := []float64{1,2,3,4}
    avg := m.Average(xs)
    fmt.Println(avg)
}

No class,but struct

class House {
    public String getHouseName() {  //method defined within class
        //implementation
    }
}
type House struct { }

func (h House) GetHouseName() string { } 
//method defined outside of struct, 
//but works on House

Java

Go

Executable Binaries

$ cd $GOPATH/src/github.com/user/hello
$ go install

This command builds the hello command, producing an executable binary

$ $GOPATH/bin/hello
Hello, world.

Go Spec

Go is a general-purpose language designed with systems programming in mind. It is strongly typed and garbage-collected and has explicit support for concurrent programming. Programs are constructed from packages, whose properties allow efficient management of dependencies. The existing implementations use a traditional compile/link model to generate executable binaries

Feature

  • Strongly Typed

  • Garbage Collected

  • Concurrent Programming

  • Package

  • No class, but structs​

  • Executable Binaries

http://golang.org/ref/spec

https://github.com/golang/go/wiki

GIS Server with Go

https://golang.org/

Go Map

  • Image Service 

 

  • Vector Service

 

  • Tile Service

 

  • Leaflet

DB Connector(pq+GORM)

type Model struct {
    ID        uint `gorm:"primary_key"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt *time.Time
}

type User struct {
    gorm.Model
    Name string
}

Web Module

https://revel.github.io/

Image Processor

llgcode -> ninjasphere

Talk is cheap, Let me show you the code

https://github.com/ehrudxo

{...}

Install Go

golang.org

Install Revel

# get revel framework
go get github.com/revel/revel

# get 'revel' command
go get github.com/revel/cmd/revel

# get samples and run chat app
go get github.com/revel/samples
revel run github.com/revel/samples/chat

&

Make a new App


$someshell/> revel new github.com/ehrudxo/MapTutorial
github.com/
    ehrudxo/
        MapTutorial/               App root
        app/               App sources
          controllers/     App controllers
            app.go         Sample Contoller
          views/           Templates
            App/           View Files
              index.html   Sample View File
            errors/        error file
          init.go          Interceptor registration
        tests/             Test suites
        conf/              Configuration files
          app.conf        Main configuration file
          routes          Routes definition
        messages/          Message files
        public/            Public assets
          css/             CSS files
          js/              Javascript files
          images/          Image files

SHAPE -> POSTGIS

1. convert shape file to sql file
shp2pgsql -I -W euc-kr -s 2097 <PATH/TO/SHAPEFILE> <DBTABLE> > SHAPEFILE.sql
2. sql loading
psql -d <DATABASE> -f SHAPEFILE.sql

GORM CODE

import "github.com/ehrudxo/GoMap/app/controllers" // add cotroller
func init() {
....
    revel.OnAppStart(controllers.InitDB)
    revel.InterceptMethod((*controllers.GormController).Begin, revel.BEFORE)
    revel.InterceptMethod((*controllers.GormController).Commit, revel.AFTER)
    revel.InterceptMethod((*controllers.GormController).Rollback, revel.FINALLY)
...
}
type GormController struct {
  *revel.Controller
  Tx *gorm.DB
}
var Db gorm.DB
func InitDB() {
  var err error
  Db, err = gorm.Open("postgres", "user=gouser dbname=postgres  password=gopassword sslmode=disable")
  if err != nil {
    revel.ERROR.Println("FATAL", err)
    panic(err)
  }
  ...
}

init.go

gorm.go

Draw2D in Go

import (
    "github.com/ninjasphere/draw2d/draw2dkit"
    "github.com/ninjasphere/draw2d/draw2dimg"
)

..

func DrawPoint( toilets []models.Toilet, b *models.Bounds, imgWidth int, imgHeight int) 
string{
    ...
      for _,toilet := range toilets{
        dx := (toilet.Geom.Lng-float64(b.Min.X))/float64(HRes)//x
        dy := float64(imgHeight) - (toilet.Geom.Lat-float64(b.Min.Y))/float64(VRes)//y
        // fmt.Println("toilet :", toilet,dx,dy);
        draw2dkit.Circle(gc, dx, dy, 3)
        gc.FillStroke()
      }
      gc.Close()
      draw2dimg.SaveToPngFile(revel.BasePath+"/output/wms/"+filename, dest)

    ...
    return filename
}

Make an Image Service

import (
    ...
	"github.com/ehrudxo/GoMap/app/services"
    ...
)
type GoMap struct {
	*revel.Controller
}
func (c GoMap) Toilet() revel.Result {
	srsNo:=2097
	c.Params.Bind(&bbox, "BBOX")
	c.Params.Bind(&srs, "SRS")
	c.Params.Bind(&widthStr, "WIDTH")
	c.Params.Bind(&heightStr, "HEIGHT")
    ...
	selectQuery:="Gid,Gu_nm,Hnr_nam,Mtc_at,Masterno,Slaveno,Neadres_nm,Wc_nam,Wc_gbn,Hd_wc_yno,Creat_de,Po_fe_nm,"
	selectQuery+="ST_Transform(Geom,3857) as Geom"
	whereQuery:="geom && ST_Transform(ST_MakeEnvelope(?,?,?,?,?),2097)"
        Db.Where(whereQuery,minx,miny,maxx,maxy,srsNo).Select(selectQuery).Find(&toilets)
    ...
        filename := services.DrawPoint( toilets, bnd, width,height )
	return c.RenderFile(file, revel.Inline )//Not an attachment. But Who disconnect the file.
}

Leaflet Settings

{{set . "title" "Home"}}
{{append . "moreStyles" "css/map.css"}}
{{append . "moreScripts" "js/jquery-1.9.1.min.js"}}
{{append . "moreScripts" "js/map.js"}}
{{template "header.html" .}}
var map
$( document ).ready(function() {
  map= L.map('map').setView([37.519459, 126.983113], 13);
  var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
  L.tileLayer(osmUrl, { attribution: '...', maxZoom: 18}).addTo(map);
  var toilet = L.tileLayer.wms("http://localhost:9000/toilet", {
    layers: 'toilet',
    format: 'image/png',
    transparent: true,
    attribution: "public toilet"
  });
  map.addLayer(toilet);
});

Toilet.html

map.js

Done!

License

ABOB License

?

A Bucket Of Beer!

image from : gettyImage

Q&A

Gis Server with Go

By Keen Dev

Gis Server with Go

  • 4,801