Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: allow to use concrete struct for func interface type parameters #37717

Closed
anjmao opened this issue Mar 6, 2020 · 3 comments
Closed
Labels
Milestone

Comments

@anjmao
Copy link

anjmao commented Mar 6, 2020

  1. I'm writing pub sub like library which expose two methods - Publish and Subscribe.
  2. Library should only allows work with protobuf message structs.
  3. Internally library knows how to send, receive bytes via network and marshal, unmarshal to proto messages.

First that comes to mind is such signature.

Library:

import  "google.golang.org/protobuf/proto"

Publish(topic string, msg proto.Message) error

Subscribe(topic string, handler func(msg proto.Message)) error

Library consumer:

import  "google.golang.org/protobuf/proto"

Publish("topic1", &MyProtoMessage{})

Subscribe("topic1", func(msg proto.Message) {
    myMsg := msg.(*MyProtoMessage)
})

Since proto.Message is interface and MyProtoMessage implements it I can pass it to Publish without any problem and do marshal internally. But there are few problems with Subscribe:

  1. In order to unmarshal Subscribe internally also need to know concrete type which is not possible.
  2. Even if it would be possible user still need to do type assertion.

My proposal is to make such Go code compile.

// MyProtoMessage implements proto.Message interface so it should be valid in this scope.
Subscribe("topic1", func(msg *MyProtoMessage) {
   
})

When reflection can be used to get concrete type from such handler parameters and would solve both issues.

Example from valid Typescript with a use of any type.

function publish(topic: string, msg: any) { }
function subscribe(topic: string, handler: (pbMsg: any) => void) {}

interface user {
	// proto fields
}

publish("user.created", {})
subscribe("user.created", (pbMsg: user) => {

})
@gopherbot gopherbot added this to the Proposal milestone Mar 6, 2020
@ghost
Copy link

ghost commented Mar 6, 2020

https://golang.org/doc/faq#covariant_types

@ianlancetaylor ianlancetaylor added v2 A language change or incompatible library change LanguageChange labels Mar 6, 2020
@ianlancetaylor
Copy link
Contributor

As noted above, this is a form of covariance for the function arguments. Also, what happens if Subscribe tries to pass a different type? Should that panic?

We've rejected that in Go, as noted in the FAQ reference above. Therefore this is a likely decline. Leaving open for four weeks for final comments.

@ianlancetaylor
Copy link
Contributor

No further comments.

@golang golang locked and limited conversation to collaborators Apr 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants