You do not do this in your program. Period. End of story.
You do this in your JCL -
//... EXEC PGM=...
//INPUT DD DISP=SHR,DSN=GDGBASE(0)
//OUTPUT DD DISP=(NEW,CATLG),...,DSN=GDGBASE(+1)
//... EXEC PGM=...
//INPUT DD DISP=OLD,DSN=GDGBASE(+1)
In the first step, the DD statement with DD name INPUT allocates the most recent generation of the data set. The DD statement with DD name OUTPUT allocates a new generation. During execution of the job, the relative generations are fixed relative to the data set status when the job started. After the job completes, the new data set specified by the DD statement with DD name OUTPUT in the first step becomes the most recent generation and is referred to by relative generation 0 in subsequent jobs.
The concept of generation data groups is completely foreign to people used to and trained in operating systems like *nix or Windoze.
The original concept of OS/360, the Great Grandfather of z/OS, was that all data set resources are specified in JCL, These designers did not want programs to be involved with this resource. Gradually, grudgingly, really, the ability for a program to specify data set resources directly was added to the system. While it is possible for individual programs to access Generation Data Group data sets by their relative generation, it is not recommended. There are many restrictions and limitations, much more so than with non Generation Data Group data sets.
Even if you think you know what you're doing, you're probably going to do it wrong. I've been using MVS and dynamic allocation for nearly 40 years. I think I know how to do GDGs. For all that, I'm not going to build anything for production. There's too much that can break.