How Go detects struct copies with sync.noCopy

(func25.dev)

19 points | by func25 4 days ago

2 comments

  • woadwarrior01 1 hour ago
    > noCopy is a special marker for types that must not be copied after their first use.

    if it looks like a hack, walks like a hack, and quacks like a hack...

    • breakingcups 28 minutes ago
      I'd want to blame Go's compatibility guarantee for this, but I can't because it wouldn't actually stop them from adding a proper solution for this..

      Just like the magic comments, it's a sad thing to see appear in this language because it feels like magic incantations one has to know that bend over backwards to not actually extend the language to fit the use case.

      • programcookie 3 minutes ago
        This shipped with Go 1.7, almost ten years ago to the day.
    • stevecoalbear 19 minutes ago
      Go's full of hacks, and holds no shame over it. Zero-initialized everything, and proceeding to 'defer' instead of RAII, generic builtin types despite lack of generics (until recently), no builtin list type, slices having capacity...

      This was Go's design philosophy until Rob Pike left - to do the simple thing simply and not try to be clever about it.

    • never_inline 1 hour ago
      Every language can't be rust.
    • neilalexander 1 hour ago
      It's not really a hack. It's a hint to a static analyser, that's all.
      • tgv 30 minutes ago
        Nah... I like Go, but this is a hack. Wiktionary --not the ultimate authority, I know, but still-- defines to hack as: To make a quick code change to patch a computer program, often one that, while being effective, is inelegant or makes the program harder to maintain.

        I could accept having an anonymous embedding as a kind of syntax directive. So many languages have had directives bolted on later, so that wouldn't be a deal breaker. But then it should be accessible in all code and (external) code should be able to implement behavior as well.

      • woadwarrior01 1 hour ago
        Most languages would encode such behavior in a trait or a protocol instead of a zero-length struct field. It's type information and ought to be encoded in the type. From that perspective, I think it is a hack.
        • kbolino 37 minutes ago
          This feels like a style complaint and not one about substance. An inaccessible (because it's named _) zero-length struct field is just another kind of metadata. It also doesn't require you to pollute the method set, which would be a bigger issue.

          The real hack to me is that anything which simply has Lock() and Unlock() methods is considered uncopyable.

          • reorder9695 29 minutes ago
            Coming from Rust anyway (can't say I'm familiar with Go), nothing about having it as a trait would pollute the method set, traits don't have to have methods (e.g. pin, unpin, send, sync, etc.). Yes a zero length field can be metadata and this is a style complaint but a struct's fields are traditionally its data and the type is its metadata, I feel like it's harmful to mix these two as I at least wouldn't generally look at fields to find metadata for the struct.
            • kbolino 21 minutes ago
              Interfaces in Go (the closest equivalent to traits in Rust) don't have to have methods either, but they are structurally typed. This is like "static duck typing" if you will. So an interface with no methods is implemented by every type in the language (indeed, this became such a useful pattern that the name "any" was reserved for it in Go 1.18).

              Marker interfaces can exist in Go, but here they are another kind of hack. They must define at least one method (which doesn't have to be public), though that method is never actually meant to be called.

            • woadwarrior01 17 minutes ago
              I'm only peripherally familiar with Go. IIRC, Rust defaults to move-only structs with the option to make them copyable with the Copy trait. Swift defaults to copyable structs (like Go), but has a ~Copyable generic type constraint to make them move-only.
        • stevecoalbear 20 minutes ago
          Go's entire schtick is being simple, eschewing language complexity in favour of telling the programmer to be careful. Like C, but with pointer safety and garbage collection.

          We learned from C++ and Rust that languages can be too smart for their own good.

          • insanitybit 16 minutes ago
            How is this simple? It's basically a hint to `go vet` that uses a special interface pattern. I'm baffled by what some people call "simple" lol
  • CamouflagedKiwi 51 minutes ago
    This feels like it should ideally be something public in the structs package so anyone can leverage it, not just a specially blessed internal thing for the sync package.