I wonder how the authors plan to accomplish a similar thing while remaining fully FFI-compatible.
92 karma · joined May 21, 2012
I wonder how the authors plan to accomplish a similar thing while remaining fully FFI-compatible.
I think it's worth quoting what Russ said in the article, which sounds very reasonable to me:
> The server would necessarily observe the source IP address in the TCP session uploading the report, but the server would not record that address with the data, a fact that can be confirmed by inspecting the reporting server source code (the server would be open source like the rest of Go) or by reference to a stated privacy policy like the one for the Go module mirror, depending on whether you lean more toward trusting software engineers or lawyers. A company could also run their own HTTP proxy to shield individual system’s IP addresses and arrange for employee systems to set GOTELEMETRY to the address of that proxy. It may also make sense to allow Go module proxies to proxy uploads, so that the existing GOPROXY setting also works for redirecting the upload and shielding the system’s IP address.
> This means that, except for the fact that I don't work in Go, most of my private conversation with a machine could be backdoored.
I don't get this. Given the design that the article is describing, how could most of your private conversation with a machine be backdoored? Specifically given that the Go tool is open source and used by millions already. Are you worried about sneaky code hidden inside that source code? If so, you should be worried already, because there's no reason that they couldn't already be doing that if they were so inclined.
It's technically not unavoidable. The Go authors could have made use of the proxy opt-in rather than opt-out, making the tool less usable as a result. A similar argument applies here, I think.
> Second, the Go telemetry would apparently create a unique, persistent user ID
Where did you see this? I scanned through the "Telemetry Design" article reasonably carefully and couldn't find any mention of this concept, and the type definition for the posted JSON (the `Report` type) doesn't seem to include any such user ID.
In the end, ISTM that you're not complaining about something that actually affects your privacy in any way, but just the _idea_ of telemetry. Is that really something worth taking such a hardline stance on?
In other words, I think you object to the Go tool already, so this is really no different?
Have you actually read the articles?
The "data put up for sale" is to be made available publicly.
IP logging can already be done (the Go proxy is enabled by default).
All the source code is open.
What's your actual problem with this, beyond a knee-jerk reaction to the idea?
I think it's interesting to observe that using the Result type is really not that much different from using a multiple return value - it's actually worse in some ways because you end up using "Unwrap" which can panic.
The answer is that the left and right side of the notch holds local equivalents to the global "given X, prove Y" connectors. You can use the left side of the notch as an input, and you can connect that up through the global blocks to prove the hypothesis.
That was non-obvious! Also, the technique of connecting the output first and making connections to nothing to see what the implied proposition is was very useful - I should have thought of that.
I have to confess I'm confused by what I believe might be the "local hypothesis block" mentioned above. The confusion is somewhat greater because the blocks don't seem to have any attached name or description, so it's not clear what they're meant to be doing.
Up until task 5 in session 2, all the solutions are pretty trivial. But I can't work out what sort of wiring that block implies (for the record, the task is "given (A->B, B->C), prove (A->C)").
It's really not clear to me what the "notch" at the top of that block implies, or how it might be used.
I think there should be at least one "hand-holding" solution for the first use of each block type. Even the papers linked to don't describe the intended semantics of each block.
Any hints here?
I agree with this, with the caveat that if you can test a package with regard to its public API only, it is desirable to do so because it gives much greater peace of mind when doing significant refactoring.
The difficulty comes in larger software where the package you're testing uses other packages as part of its implementation which also have their own time-based logic. Do we export all those synchronisation points so that importers can use them to help their tests too? If we do, then suddenly our API surface is significantly larger and more fragile - what would have been an internal fix can become a breaking change for many importers.
This is a common misapprehension. Actually, even if you fully mock out time, you can still get race conditions, because goroutines can remain active regardless of the state of the clock, and there's no general way to wait until all goroutines are quiescent waiting on the clock. This is not just a theoretical concern - this kind of problem is not uncommon in practice.
I think clock-mocking can be very useful for testing hard-to-reach places in leaf packages. But at a higher level, I think it can end up producing extremely fragile tests that depend intimately on implementation details of packages that the tests should not be concerned about at all. In these cases, I've come to prefer configuring short time intervals and polling for desired state as being the lesser of two evils.
Aside: the conflicts mentioned in the article should never be a real problem because you can always resolve the conflict by just recreating the dependences.tsv file (you should never be editing it manually anyway).
See https://github.com/golang/go/issues/11513 and https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVP... for some background.
In order to do evil things like convert raw bytes to floats,
I chose to use the “unsafe” package
FWIW you don't need unsafe to do that. encoding/binary + http://golang.org/pkg/math/#Float64frombits will do the job just fine.For example, bufio.NewReader would probably, in a language with generics, be phrased as a type with respect to a type parameter. Something like (in bastard Haskell)
class Reader a where
Read :: a -> [Char]
newReader :: (Reader a) => a -> BufioReader a
In Go, it's: package bufio
func NewReader(r io.Reader) *Reader
The interface argument is implicitly a type parameter here.This subset of generics covers a wide range of software components, even if it doesn't include the usual container types.
In my experience of Go, this is not actually true. For example, in the latest project I've been working on, there are 8487 lines of non-test code. In that code, there are a total of 16 dynamic casts, more than half of which are checked (mostly checking for particular error types). There are a total of 4 occurrences which might possibly be amenable to generics.
The type system is totally relevant, and checks 99.9% of our code.
Well, not that small, i guess :-)
Then a handler function could look like this:
func Do(w http.ResponseWriter, r *http.Request, params *DoParams) {
w.Write([]byte(params.Var))
}
No need for any dynamic type coercion - it can all be checked up front when the handlers are registered. The down side is that the signature of Handle would become more opaque (its argument would just be an interface{}) and you'd probably want to lose the Handler type.FWIW, passing an empty struct for the sole purpose of being inspected using reflection is not unusual (see for example gob.Register).
type Config struct {
a int
b string
c float
d interface{}
}
var defaultConfig = Config{
a: 11,
b: "some default",
c: 55.5,
d: new(D),
}
func f(cfg Config) {
// ...
}
func main() {
cfg := defaultConfig
cfg.c = 44.4
f(cfg)
}
having the "keyword" arguments as a separate type
makes them potentially useful as a currency to pass
to other functions too, rather than as a set of attributes
and values defined for one function only.