-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgolab-2017-talk.slide
323 lines (172 loc) · 12.7 KB
/
golab-2017-talk.slide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
The gopher's guide to mobile apps
GoLab Florence 2017
Elias Naur
@elias_naur
: Imagine you’re a programmer having discovered Go and decided that writing programs in Go is so much more fun and productive for you
: If you’re a so backend programmer, you’re in luck; there are more and more ways you can use Go for your infrastructure and servers.
: If like writing the programs that end up on people’s phones or tablets, you’re not so lucky. You’ll be writing your app in Java while you stare longingly at your backend programmers.
: And then when you’re done, you start all over in Objective-C or Swift. Or you get someone else to do it for you. Or less lucky, simultaneous development, with all those incompatibilities and differences.
: I’ve written just too much Java code in my life. If I had my way, I’d never write another line of Java again. In fact, I’d rather spend double the time writing code to avoid it.
: This is how I started working with Go Mobile, and this talk will be about how you can write less Java, Objective-C or Swift code and more Go code for both mobile platforms. In fact, I'll show how you can even avoid writing any Java code at all!
* Background
Go Mobile started in 2014.
Used by several companies and projects:
- The go-ethereum project uses Go Mobile for its Android/iOS clients.
- Zen.ly. Android/iOS apps. Native UI, business logic in Go.
- Trakref. Android/iOS apps. React Native UI, business logic Go.
: The Go Mobile project has been around for quite a while, since 2014 in fact.
: Quite a few companies and projects have started to incorporate it. Of the few I know about, there's the Go ethereum client, and the cross platform apps by Zen.ly and Trakref. Feel free to send me more references, by the way; numbers alone don't guarantee quality but it's a good indicator.
* A basic Android app
: Let's start with a very basic Android app. Gomobile supports iOS just as well, but I know Android best, so that's what I'll show you today.
* build.xml
.code basic1/build.gradle /START 1 OMIT/,/END 1 OMIT/
: First, the build.gradle plugin. It's all pretty boiler plate.
* build.xml (cont.)
.code basic1/build.gradle /START 2 OMIT/,/END 2 OMIT/
: We're specifying the app id, SDK version and that we'd like to use the support library. A little long, but nothing surprising if you've done Android before. We'll enable the data binding library because that helps cut down on boilerplate Java code. And remember, we don't want to write Java code.
* AndroidManifest.xml
.code basic1/src/main/AndroidManifest.xml
: The manifest is also as basic as you can get. It specifes a single activity, or window if you like.
* themes.xml
.code basic1/src/main/res/values/themes.xml
: The theme file is not required, but very handy to give you app a consistent look.
* activity_main.xml
.code basic1/src/main/res/layout/activity_main.xml
: The layout file is the content of our single Activity.
* MainActivity.java
.code basic1/src/main/java/org/golang/example/basic/MainActivity.java
: And finally, a very sparse Java class to represent this app's single Activity.
* The basic app
.image screenshots/basic1.png _ 300
: So far so good. But where's the Go code?
* The gobind gradle plugin
Add the gobind plugin to build.xml:
.code account/build.gradle /START 1 OMIT/,/END 1 OMIT/
Then, apply it:
.code account/build.gradle /START 2 OMIT/,/END 2 OMIT/
: Now, let's add some Go! First, we'll need to enable the gobind plugin in the build.xml file.
: Gobind only needs a single package, but you can list multiple by separating them with spaces.
* A simple account
account.go
.code src/goaccount/account.go /START 1 OMIT/,/END 1 OMIT/
: So let's say your app is about banking and that our activity is showing your account, as well as its transactions. We'll define the Account and Transaction data types first...
* A simple account (cont.)
.code src/goaccount/account.go /START 2 OMIT/,/END 2 OMIT/
: ...and add methods to manipulate them.
* View account
MainActivity.java
.code account/src/main/java/org/golang/example/basic/MainActivity.java /START 1 OMIT/,/END 1 OMIT/
: We'll need a little more Java to hook it all up. First, we create an account, add a few transactions and then pass it on to the layout.
: Notice how the Account and Transaction class are both generated by gomobile so they're readily useable from Java.
* View account (cont.)
activity_main.xml
.code account/src/main/res/layout/activity_main.xml /<data>/,/formatBalance/
: We've added a binding variable, account, and hooked up its formatBalance to the TextView.
* View account (cont.)
.image screenshots/account_balance.png _ 500
: So far, so good. We're successfully showing data from Go. Even the balance seems to be correct.
* Transactions
activity_main.xml
.code account/src/main/res/layout/activity_main.xml /RecyclerView/,/vertical/
: Let's show the transactions. To do that the proper and modern way (and we do like to be proper and modern), we'll need a RecyclerView.
* Transaction (cont.)
MainActivity.java
.code account/src/main/java/org/golang/example/basic/MainActivity.java /START 2 OMIT/,/END 2 OMIT/
* Transaction (cont.)
: ...And Java code to hook it all up
.code account/src/main/java/org/golang/example/basic/MainActivity.java /START 3 OMIT/,/END 3 OMIT/
: ...an Adapter to expose the transactions from Go.
* Transaction (cont.)
.code account/src/main/java/org/golang/example/basic/MainActivity.java /START 4 OMIT/,/END 4 OMIT/
: ...an, FINALLY (phew), the ViewHolder to, well, hold a transaction. Oh, where would we be, if we didn't have ViewHolders to hold our views?
* Transaction (cont.)
.image screenshots/account_trans.png _ 500
: And violá! The complete account overview, with its balance and transactions. But wait.
: This is a conference about Go, and I've spent considerable amount of Java code just to view the data from two slides of Go. What happened to the part where there would be _less_ Java code?
: Let's be adventurous and get rid of that Java code and rewrite MainActivity in Go with Go Mobile's reverse binding generator.
* GoActivity
goact_android.go
.code src/goaccount/goact_android.go
: We'll call it GoActivity, and it looks very similar to its Java counterpart and is in fact a complete Android Activity written entirely in Go. There's a lot of magic here, so let's break it down into parts.
* GoActivity (cont.)
.code src/goaccount/goact_android.go HLimport
: First, gomobile allows you to import Java packages as if they were written in Go.
: In this case, the java android.os package and android support library app package is imported. Behind your back, Go Mobile generates Go wrappers for you so you can access classes from those packages.
: Something similar applies to Objective-C in iOS land.
* GoActivity (cont.)
.code src/goaccount/goact_android.go HLembed
: If you remember the Account and Transaction type from earlier, gomobile generates Java classes for you. Gomobile also allows you to specify what existing Java class to extend or Java interface to implement. You describe this by embedding the Go type representing the Java type.
: In this case, gomobile will generate a GoActivity class that extends the AppCompatActivity class from the support library.
* GoActivity (cont.)
AndroidManifest.xml
.code goaccount/src/main/AndroidManifest.xml
: To use GoActivity, we'll write it into the manifest as if it were any other Java Activity.
* GoActivity (cont.)
.code src/goaccount/goact_android.go HLoncreate
: To override methods from its super class AppCompatActivity, add a Go method with the method name with its initial letter capitalized.
: Gomobile uses the argument and return types to exactly match the correct method. In our case, we'll match the OnCreate method that takes a android.os.Bundle.
: Now, why did I say os.Bundle? What about the parameter called this?
: To understand that, you'll have to realize that every time a your code or the Android SDK creates a new instance of the Java class GoActivity, a Go instance of the GoActivity struct is created as well.
: When the Go OnCreate method is called, you only have access to the Go instance stored in the variable a. To represent the Java instance, gomobile allows you to add a special parameter, this.
* GoActivity (cont.)
.code src/goaccount/goact_android.go HLgopkg
: So what's the type of that parameter? Again, there are two types involved, the Go type GoActivity and the Java class GoActivity. The this parameters needs to be of the Java type, so we import the Java representation of the goaccount package, rename it gopkg and use its GoActivity type.
* GoActivity (cont.)
.code src/goaccount/goact_android.go HLsuper
: Finally, every such wrapper type exports a method called Super that you can use to call super methods. In this case, we need to pass along the bundle to GoActivity's super class.
: We'll get to the setupActivity function in a moment.
* GoActivity (cont.)
.image screenshots/goaccount.png _ 300
: And that's it! Gone is the MainActivity and we have an Android Activity entirely in Go. Now, let's implement setupActivity
* setupActivity
.code src/goaccount/goact2_android.go /START SETUP OMIT/,/END SETUP OMIT/ HLdatabinding
: First, we'll instantiate the databinding Java class. Gomobile doesn't understand generic types, so we have to use the special method Cast to cast the result from SetContentView to the specific binding class.
* setupActivity
.code src/goaccount/goact2_android.go /START SETUP OMIT/,/END SETUP OMIT/ HLrecyclerview
: Then, we find the recyclerview and setup its layout manager.
* setupActivity
.code src/goaccount/goact2_android.go /START SETUP OMIT/,/END SETUP OMIT/ HLadapter
: After creating an account and adding its transactions, we create a TransactionsAdapter. Notice that we use the New function to create a Java instance not just a Go instance.
: Then, we can access the wrapped Go instance with the Unwrap method and assign to it.
* TransactionsAdapter
.code src/goaccount/goact2_android.go /START TRANSADAPTER OMIT/,/END TRANSADAPTER OMIT/
: This is the Go version of the TransactionsHolder. It extends RecyclerView.Adapter and holds a slice of transactions.
* TransactionHolder
.code src/goaccount/goact2_android.go /START TRANSHOLDER OMIT/,/END TRANSHOLDER OMIT/
: And this is the TransactionHolder. Even Go needs to hold on to things.
* GoActivity (cont.)
.image screenshots/goaccount_trans.png _ 500
: And finally, we're back to where we started! Not even a single line of Java in sight. It's all in Go.
* The Toy Wallet
: So, is it really worth it to go through all this trouble to avoid Java code?
: I believe it matters for non-trivial code bases, either internal in your organization or open source software. To demonstrate this, let's first take a small detour.
* Bitcoin
- Digital currency
- Decentralized architecture, no single point of trust.
- Complexity is in the nodes.
: Bitcoin is, as you might know, a new digital currency. It is decentralized and contain no single point of failure nor trust.
: It also means that the implementation of the Bitcoin protocol necessarily lies in its participating nodes.
: In other words, there's no backend to offload the complexity.
* btcsuite
.link github.com/btcsuite
- btcsuite, a Go implementation of the Bitcoin protocol
- btcd, the bitcoin daemon
- btcrpcclient, the bitcoin RPC client
: btcsuite is a complete Go implementation of the Bitcoin protocol.
: It contains a fully functioning btcd daemon capable of participating in the Bitcoin network
: It also contains an rpc client, which is capable of communicating with a bitcoin node.
* demo
: This is a simple bitcoin wallet written entirely in Go, much like the mock account app we saw earlier.
: It runs in test mode, which is a parallel bitcoin network. It is the same protocol as the main Bitcoin network, but its coins are worthless, by convention.
: It tracks the balance and transactions a single bitcoin address, or account if you will.
: The wallet is connected to a btcsuite btcd daemon. The node runs on my laptop, but it might as well run anywhere on the internet.
: The btcd daemon participates in the Bitcoin network and the Android wallet asks it to track transactions to its address.
: Let's see it action. I have on my crusty old Android phone another wallet, Mycelium, capable of transferring test Bitcoins.
: Clicking this button in the demo app brings up a QR code encoding its address. Scanning that address with Mycelium allows me to transfer coins to it.
: There, I'll transfer XX mBTC... And there we go, the transactions pops up and the balance is updated.
* Summary
- Use Go Mobile to share non-trivial Go across mobile platforms Android/iOS.
- Use the reverse bindings with care; they're still experimental.
- Look out for reference cycles, when references cross the language barriers.
* Questions