I am writing a game project in Go and I am using an OpenGl 3.3 core context to do my rendering stuff. At the moment I have different types of renderers. Each renderer has it's own pair of vertex- and fragment-shader, a struct of uniform- and attribute locations. A struct with glBuffers, vertex-array-object, and numverts (int) which contains all data required to render one object (mesh). Last but not least a constructor to create and initialize the attribute/uniform locations a method to load a mesh into mesh data and the render method itself.
I am absolutely not happy with this design. Every time I want to create a new simple shader, I have to write all this code, and I haven't found a way to make the overhead of a new shader smaller. All I was able to make with the help of go reflections is to automatically get the attribute/uniform location based on the variable name in attribute/uniform location struct and to automatically set the attribute pointers based on the layout of the vertex struct.
another thing that I don't like, is that when I want to implement for example the functionality of the function glClipPlane of the fixed function pipeline, I need to add the uniform to each shader separately and I need to set this uniform in each shader and I need to implement the discard of fragments in each fragment shader
Are there some common practices that significantly reduce the code overhead of a new shader? Are there good shader pipelines that you can recommend me to take a look at? Are there some good practices to add functionality to several shaders at once?