github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/doc/go-tour.md (about) 1 [Home](../README.md) ยป 2 3 [Technical Overview](intro.md) | [Use Cases](../README.md#use-cases) | [Command-Line Interface](cli-tour.md) | **Go bindings Tour** | [Path Syntax](spelling.md) | [FAQ](faq.md) 4 <br><br> 5 # A Short Tour of Noms for Go 6 7 This is a short introduction to using Noms from Go. It should only take a few minutes if you have some familiarity with Go. 8 9 During the tour, you can refer to the complete [Go SDK Reference](https://godoc.org/github.com/attic-labs/noms) for more information on anything you see. 10 11 12 13 ## Requirements 14 15 * [Noms command-line tools](https://github.com/attic-labs/noms#setup) 16 * [Go v1.6+](https://golang.org/dl/) 17 * Ensure your [$GOPATH](https://github.com/golang/go/wiki/GOPATH) is configured 18 19 ## Start a Local Database 20 21 Let's create a local database to play with: 22 23 ```sh 24 > mkdir /tmp/noms-go-tour 25 > noms serve /tmp/noms-go-tour 26 ``` 27 28 ## [Database](https://github.com/attic-labs/noms/blob/master/go/datas/database.go) 29 Leave the server running, and in a separate terminal: 30 31 ```sh 32 > mkdir noms-tour 33 > cd noms-tour 34 ``` 35 36 Then use your favorite editor so that we can start to play with code. To get started with Noms, first create a Database: 37 38 ```go 39 package main 40 41 import ( 42 "fmt" 43 "os" 44 45 "github.com/attic-labs/noms/go/spec" 46 ) 47 48 func main() { 49 sp, err := spec.ForDatabase("http://localhost:8000") 50 if err != nil { 51 fmt.Fprintf(os.Stderr, "Could not access database: %s\n", err) 52 return 53 } 54 defer sp.Close() 55 } 56 ``` 57 58 Now let's run it: 59 60 ```sh 61 > go run noms-tour.go 62 ``` 63 64 If you did not leave the server running you would see output of ```Could not access database``` here, otherwise your program should exit cleanly. 65 66 See [Spelling in Noms](https://github.com/attic-labs/noms/blob/master/doc/spelling.md) for more information on database spec strings. 67 68 69 ## [Dataset](https://github.com/attic-labs/noms/blob/master/go/dataset/dataset.go) 70 71 Datasets are the main interface you'll use to work with Noms. Let's update our example to use a Dataset spec string: 72 73 ```go 74 package main 75 76 import ( 77 "fmt" 78 "os" 79 80 "github.com/attic-labs/noms/go/spec" 81 ) 82 83 func main() { 84 sp, err := spec.ForDataset("http://localhost:8000::people") 85 if err != nil { 86 fmt.Fprintf(os.Stderr, "Could not create dataset: %s\n", err) 87 return 88 } 89 defer sp.Close() 90 91 if _, ok := sp.GetDataset().MaybeHeadValue(); !ok { 92 fmt.Fprintf(os.Stdout, "head is empty\n") 93 } 94 } 95 ``` 96 97 Now let's run it: 98 99 ```sh 100 > go run noms-tour.go 101 head is empty 102 ``` 103 104 Since the dataset does not yet have any values you see ```head is empty```. Let's add some data to make it more interesting: 105 106 ```go 107 package main 108 109 import ( 110 "fmt" 111 "os" 112 113 "github.com/attic-labs/noms/go/spec" 114 "github.com/attic-labs/noms/go/types" 115 ) 116 117 func newPerson(givenName string, male bool) types.Struct { 118 return types.NewStruct("Person", types.StructData{ 119 "given": types.String(givenName), 120 "male": types.Bool(male), 121 }) 122 } 123 124 func main() { 125 sp, err := spec.ForDataset("http://localhost:8000::people") 126 if err != nil { 127 fmt.Fprintf(os.Stderr, "Could not create dataset: %s\n", err) 128 return 129 } 130 defer sp.Close() 131 132 db := sp.GetDatabase() 133 134 data := types.NewList(db, 135 newPerson("Rickon", true), 136 newPerson("Bran", true), 137 newPerson("Arya", false), 138 newPerson("Sansa", false), 139 ) 140 141 fmt.Fprintf(os.Stdout, "data type: %v\n", types.TypeOf(data).Describe()) 142 143 _, err = db.CommitValue(sp.GetDataset(), data) 144 if err != nil { 145 fmt.Fprint(os.Stderr, "Error commiting: %s\n", err) 146 } 147 } 148 ``` 149 150 Now you will get output of the data type of our Dataset value: 151 152 ```shell 153 > go run noms-tour.go 154 data type: List<struct { 155 given: String 156 male: Bool 157 }> 158 ``` 159 160 Now you can access the data via your program: 161 162 ```go 163 package main 164 165 import ( 166 "fmt" 167 "os" 168 169 "github.com/attic-labs/noms/go/spec" 170 "github.com/attic-labs/noms/go/types" 171 ) 172 173 func main() { 174 sp, err := spec.ForDataset("http://localhost:8000::people") 175 if err != nil { 176 fmt.Fprintf(os.Stderr, "Could not create dataset: %s\n", err) 177 return 178 } 179 defer sp.Close() 180 181 if headValue, ok := sp.GetDataset().MaybeHeadValue(); !ok { 182 fmt.Fprintf(os.Stdout, "head is empty\n") 183 } else { 184 // type assertion to convert Head to List 185 personList := headValue.(types.List) 186 // type assertion to convert List Value to Struct 187 personStruct := personList.Get(0).(types.Struct) 188 // prints: Rickon 189 fmt.Fprintf(os.Stdout, "given: %v\n", personStruct.Get("given")) 190 } 191 } 192 ``` 193 194 Running it now: 195 196 ```sh 197 > go run noms-tour.go 198 given: Rickon 199 ``` 200 201 You can see this data using the command-line too: 202 203 ```sh 204 > noms ds http://localhost:8000 205 people 206 207 > noms show http://localhost:8000::people 208 struct Commit { 209 meta: struct {}, 210 parents: set {}, 211 value: [ // 4 items 212 struct Person { 213 given: "Rickon", 214 male: true, 215 }, 216 struct Person { 217 given: "Bran", 218 male: true, 219 }, 220 struct Person { 221 given: "Arya", 222 male: false, 223 }, 224 struct Person { 225 given: "Sansa", 226 male: false, 227 }, 228 ], 229 } 230 ``` 231 232 Let's add some more data. 233 234 ```go 235 package main 236 237 import ( 238 "fmt" 239 "os" 240 241 "github.com/attic-labs/noms/go/spec" 242 "github.com/attic-labs/noms/go/types" 243 ) 244 245 func main() { 246 sp, err := spec.ForDataset("http://localhost:8000::people") 247 if err != nil { 248 fmt.Fprintf(os.Stderr, "Could not create dataset: %s\n", err) 249 return 250 } 251 defer sp.Close() 252 253 if headValue, ok := sp.GetDataset().MaybeHeadValue(); !ok { 254 fmt.Fprintf(os.Stdout, "head is empty\n") 255 } else { 256 // type assertion to convert Head to List 257 personList := headValue.(types.List) 258 personEditor := personList.Edit() 259 data := personEditor.Append( 260 types.NewStruct("Person", types.StructData{ 261 "given": types.String("Jon"), 262 "family": types.String("Snow"), 263 "male": types.Bool(true), 264 }), 265 ).List() 266 267 fmt.Fprintf(os.Stdout, "data type: %v\n", types.TypeOf(data).Describe()) 268 269 _, err = sp.GetDatabase().CommitValue(sp.GetDataset(), data) 270 if err != nil { 271 fmt.Fprint(os.Stderr, "Error commiting: %s\n", err) 272 } 273 } 274 } 275 ``` 276 277 Running this: 278 279 ```sh 280 > go run noms-tour.go 281 data type: List<Struct Person { 282 family?: String, 283 given: String, 284 male: Bool, 285 }> 286 ``` 287 288 Datasets are versioned. When you *commit* a new value, you aren't overwriting the old value, but adding to a historical log of values: 289 290 ```sh 291 > noms log http://localhost:8000::people 292 commit ba3lvopbgcqqnofm3qk7sk4j2doroj1l 293 Parent: f0b1befu9jp82r1vcd4gmuhdno27uobi 294 (root) { 295 + struct Person { 296 + family: "Snow", 297 + given: "Jon", 298 + male: true, 299 + } 300 } 301 302 commit f0b1befu9jp82r1vcd4gmuhdno27uobi 303 Parent: hshltip9kss28uu910qadq04mhk9kuko 304 305 commit hshltip9kss28uu910qadq04mhk9kuko 306 Parent: None 307 ``` 308 309 ## Values 310 311 Noms supports a [variety of datatypes](https://github.com/attic-labs/noms/blob/master/doc/intro.md#types) beyond List, Struct, String, and Bool we used above. 312 313 ## Samples 314 315 You can continue learning more about the Noms Go SDK by looking at the documentation and by reviewing the [samples](https://github.com/attic-labs/noms/blob/master/samples/go). The [hr sample](https://github.com/attic-labs/noms/blob/master/samples/go/hr) is a more complete implementation of our example above and will help you to see further usage of the other datatypes.