Skip to content

Instantly share code, notes, and snippets.

@icub3d
Created July 31, 2013 13:20
Show Gist options
  • Save icub3d/6121908 to your computer and use it in GitHub Desktop.
Save icub3d/6121908 to your computer and use it in GitHub Desktop.
Protobuf in Go
package main;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
$ protoc --go_out=. addressbook.proto
$ go build
$ ./addressbook
proto> new
ID: 1
Name: josh
Email: joshua@themarshians.com
Phone (blank to finish): 801-879-2250
Type (home,work,mobile): mobile
Phone (blank to finish):
proto> write data
proto> quit
$ ./addressbook
proto> list
proto> read data
proto> list
name:"josh" id:1 email:"joshua@themarshians.com" phone:<number:"801-879-2250" type:MOBILE >
proto> quit
package main
import (
"bufio"
"code.google.com/p/goprotobuf/proto"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
var addressbook AddressBook
func main() {
scanner := bufio.NewScanner(os.Stdin)
quit := false
for !quit {
fmt.Print("proto> ")
if !scanner.Scan() {
break
}
line := scanner.Text()
parts := strings.Split(line, " ")
cmd := parts[0]
args := parts[1:]
switch cmd {
case "list":
for _, p := range addressbook.Person {
fmt.Println(p)
}
case "find":
for _, p := range addressbook.Person {
if strconv.Itoa(int(*p.Id)) == args[0] {
fmt.Println(p)
break
}
}
case "new":
if !newPerson(scanner) {
quit = true
break
}
case "read":
if err := read(args[0]); err != nil {
fmt.Println(err)
}
case "write":
if err := write(args[0]); err != nil {
fmt.Println(err)
}
case "quit":
quit = true
default:
fmt.Println("unrecognized command:", cmd, args)
}
}
if err := scanner.Err(); err != nil {
fmt.Println("reading stdin:", err)
}
}
func write(filename string) error {
b, err := proto.Marshal(&addressbook)
if err != nil {
return fmt.Errorf("encoding addressbook:", err)
}
return ioutil.WriteFile(filename, b, os.ModePerm)
}
func read(filename string) error {
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("opening file:", err)
}
defer file.Close()
b, err := ioutil.ReadAll(file)
if err != nil {
return fmt.Errorf("reading file:", err)
}
err = proto.Unmarshal(b, &addressbook)
if err != nil {
return fmt.Errorf("decoding file:", err)
}
return nil
}
func newPerson(scanner *bufio.Scanner) bool {
fmt.Print("ID: ")
if !scanner.Scan() {
return false
}
i, err := strconv.ParseInt(scanner.Text(), 10, 32)
if err != nil {
return false
}
var id int32 = int32(i)
fmt.Print("Name: ")
if !scanner.Scan() {
return false
}
name := scanner.Text()
fmt.Print("Email: ")
if !scanner.Scan() {
return false
}
email := scanner.Text()
p := &Person{
Id: &id,
Name: &name,
Email: &email,
}
for {
fmt.Print("Phone (blank to finish): ")
if !scanner.Scan() {
return false
}
number := scanner.Text()
if number == "" {
break
}
fmt.Print("Type (home,work,mobile): ")
if !scanner.Scan() {
return false
}
numberType := Person_HOME
switch scanner.Text() {
case "work":
numberType = Person_WORK
case "mobile":
numberType = Person_MOBILE
case "home":
numberType = Person_HOME
default:
fmt.Println("unrecognized type, using 'home'")
}
p.Phone = append(p.Phone, &Person_PhoneNumber{
Number: &number,
Type: &numberType,
})
}
addressbook.Person = append(addressbook.Person, p)
return true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment