Native Mac APIs for Go
github.com
github.com
For those interested in a Rust variant, I've been hacking on one for awhile: https://github.com/ryanmcgrath/cacao
I wouldn't say it's yet ready for production use, but so far it's working pretty well for me. Been dogfooding it by building an app I've wanted for a bit - a proper magic-wormhole macOS app.
One of the things I've really wanted to keep to is the delegate pattern, since I think it actually works really well for Rust's model. A fun example I finished yesterday is ListView cell reuse:
https://twitter.com/ryanmcgrath/status/1357097991081844737/p...
Ultimately I view this as one of the last pieces needed for a cross-platform Rust UI framework to actually work.
In my own projects, I had to wrap calls from foreign threads into AppKit APIs with an @autoreleasepool {} block or my app would leak memory. [1]
[1] https://developer.apple.com/library/archive/documentation/Co...
Unfortunately I can afford some leaks at the moment, so if that's critical to anybody else and I'm doing something wrong just submit a PR
See here: https://developer.apple.com/library/archive/documentation/Co...
> Cocoa always expects code to be executed within an autorelease pool block, otherwise autoreleased objects do not get released and your application leaks memory
I have a hard time keeping up with their changes but you might be right: https://developer.apple.com/documentation/foundation/nsautor...
Oddly it says you cannot use them directly, but later implies maybe they are just less efficient. It would be nice if somebody made an issue for this.
1. If you're compiling Objective C in ARC mode, you can't use NSAutoreleasePool directly, and must instead use @autoreleasepool.
2. In manual reference counting mode you can use either NSAutoreleasePool or @autoreleasepool, but the latter has lower overhead. (This may matter if e.g. you're draining the autorelease pool on every iteration of a loop to reduce memory spikes.)
Under the hood -- at least on the version I disassembled -- NSAutoreleasePool's -init and -release methods wrap the CoreFoundation CFAutoreleasePoolPush and CFAutoreleasePoolPop functions, which in turn call the runtime's objc_autoreleasePoolPush and objc_autoreleasePoolPop functions, which are the things that @autoreleasepool will cause the compiler to emit directly.
This answer looks like a better overview of what the runtime is doing: https://stackoverflow.com/a/21010442
The @autoreleasepool block seems equivalent to this:
ctx = _objc_autoreleasePoolPush()
defer _objc_autoreleasePoolPop(ctx)
You could maybe provide sugar for it like this: https://play.golang.org/p/dljXN3BdEGrCalling the `_objc_autoreleasePoolXX` functions are still likely to be faster than the NSAutoreleasePool objects, but only because you're avoiding the Objective-C message sends.
I haven't actually used k8s-backed Dokku, but I imagine that it would be worth at least experimenting with if you're already committed to running stuff on k8s.
I'm a former lover of Heroku and maintainer of Dokku.
Manage it with CDK or terraform. As long as you have enough containers running, spot ends up being a non issue.
So I put together an open-source Terraform super-module to automatically set all of that up in a few lines of code.
I'm a pretty big fan of CDK if you are willing to make cloudformation and AWS your lingua franca. I use it for most of my personal projects, but professionally bias towards terraform.
AWS lambda can run plain old docker containers now too. Check out something like the serverless framework to make it easy to define a bunch of web services or APIs and deploy to lambda, knative, etc.
Not the author, but yes. Go calling C is expensive, and that's precisely how this works. Whether or not that matters for your use case is another topic.
https://www.cockroachlabs.com/blog/the-cost-and-complexity-o...
In their benchmark, calling a `func() {}` in Go vs a `void foo() {}` in C (via CGo) is almost 100x faster.
$ go test -bench . -gcflags '-l' # disable inlining for fairness
BenchmarkCGO-8 10000000 171 ns/op
BenchmarkGo-8 2000000000 1.83 ns/op
EDIT: And then you still have the extra overhead when using `C.CString` and `C.GoBytes` if you're passing those sorts of arguments to C.Is this true even if only primitives are passed and returned? If so, why? For comparison, Java is fast at that these days, if I understand correctly.
(Interesting related reading regarding Java: https://web.archive.org/web/20160304055443/http://nerds-cent... )
Recently I looked at couple of options of writing some Golang to make a simple GUI app that would look natively on Windows/MacOS (text area, several checkboxes/buttons), and there's no much there to be honest.
Seriously, this is the only option if you care not just about looks but also about feel, because no cross-platform toolkit gets things like keyboard shortcuts, scrolling inertia, menu mnemonics, etc. correct on all platforms they target. Not to mention platform accessibility features.
Surely most of the work in your app is platform-independent, right? Plumbing data into platform-specific UIs should not be a hard endeavor.
Users won’t care, there’s no award
This seems like a much more general and useful solution, excited to switch some things over to it!
[1] https://github.com/caseymrm/go-pmset
However, I think it's problematic that modern languages (Go, Rust) don't provide these kinds of bindings out of the box. I honestly think it's probably starting to be "in-scope" for standard libraries. I'm working on a side-project now which needs a desktop app, and I'm actually using Fyne[1] because it makes cross-platform development semi-easy (even though it doesn't look native, nor particularly great). The alternative is using either Electron or using something like this for OSX, using something else for Windows, and using something else for Linux.
Window/widget/notification/taskbar APIs are stable for all major operating systems, and it seems like we keep reinventing the wheel here.
[1] https://fyne.io/
Do they mean the abandoned GC system Apple tried, or the obsolete manual pool-based system Apple used to use?
Either way, I want ARC instead.
ARC is a compiler trick in the clang objective-c and swift compilers-- essentially injecting the appropriate retain/release calls for you. You won't get that for free in Go (because, again, it's a compiler feature-- compiled ObjC/Swift code is still calling retain/release just like you would manually), but I'd expect some integration with Go's memory management system so you're not having to make those calls manually. (It looks like that is not here in this particular release, though-- they have retain/release calls in some of their examples.)
Objective-C garbage collection is not a thing any more, and hasn't been for quite some time. Deprecated back in macOS 10.8, and outright removed in more recent versions of the runtime (it was never available on iOS, and was taken out sometime around macOS 10.12 on desktop).
The author has already clarified that Objective-C "garbage collection" wasn't really what he meant, but the distinction between ARC and MRC only makes sense in the context of the ObjC compiler itself. From the "outside", esp. for compiled binaries (like the system frameworks), ObjC classes always just use reference counting.
There was no option to use anything else. Has that changed?
Usually these garner early interest, but no significant programs come out using them, and they tend to be abandoned within a few years. I don't mean to discourage the author, but I wonder if he's aware of the history and if he has thoughts on why Go may fare better.
Otherwise this worked really well and intuitively for a golang dev!